diff --git a/resources/models/sl1_bed.stl b/resources/models/sl1_bed.stl
new file mode 100644
index 000000000..28601b288
Binary files /dev/null and b/resources/models/sl1_bed.stl differ
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index acaba9d6a..1ef6c7b84 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -1125,7 +1125,7 @@ std::string Print::validate() const
         // Check horizontal clearance.
         {
             Polygons convex_hulls_other;
-            for (PrintObject *object : m_objects) {
+            for (const PrintObject *object : m_objects) {
                 // Get convex hull of all meshes assigned to this print object.
                 Polygon convex_hull;
                 {
@@ -1186,46 +1186,63 @@ std::string Print::validate() const
             return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors.");
         if (! m_config.use_relative_e_distances)
             return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
-        SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
 
-        const PrintObject* tallest_object = m_objects.front(); // let's find the tallest object
-        for (const auto* object : m_objects)
-            if (*(object->layer_height_profile.end()-2) > *(tallest_object->layer_height_profile.end()-2) )
-                    tallest_object = object;
-
-        for (PrintObject *object : m_objects) {
-            SlicingParameters slicing_params = object->slicing_parameters();
-            if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
-                std::abs(slicing_params.layer_height             - slicing_params0.layer_height            ) > EPSILON)
-                return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
-            if (slicing_params.raft_layers() != slicing_params0.raft_layers())
-                return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
-            if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
-                return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
-            if (! equal_layering(slicing_params, slicing_params0))
-                return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
-
-            if (m_config.variable_layer_height) { // comparing layer height profiles
-                bool failed = false;
-                // layer_height_profile should be set by Print::apply().
-                if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size()) {
-                    int i = 0;
-                    while (i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) {
-                        if (std::abs(tallest_object->layer_height_profile[i] - object->layer_height_profile[i])) {
-                            failed = true;
-                            break;
-                        }
-                        ++i;
-                        if (i == object->layer_height_profile.size()-2) // this element contains this objects max z
-                            if (tallest_object->layer_height_profile[i] > object->layer_height_profile[i]) // the difference does not matter in this case
-                                ++i;
-                    }
+        if (m_objects.size() > 1) {
+            bool                                has_custom_layering = false;
+            std::vector<std::vector<coordf_t>>  layer_height_profiles;
+            for (const PrintObject *object : m_objects) {
+                has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty();
+                if (has_custom_layering) {
+                    layer_height_profiles.assign(m_objects.size(), std::vector<coordf_t>());
+                    break;
                 }
-                else
-                    failed = true;
+            }
+            SlicingParameters slicing_params0    = m_objects.front()->slicing_parameters();
+            size_t            tallest_object_idx = 0;
+            if (has_custom_layering)
+                PrintObject::update_layer_height_profile(*m_objects.front()->model_object(), slicing_params0, layer_height_profiles.front());
+            for (size_t i = 1; i < m_objects.size(); ++ i) {
+                const PrintObject      *object         = m_objects[i];
+                const SlicingParameters slicing_params = object->slicing_parameters();
+                if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
+                    std::abs(slicing_params.layer_height             - slicing_params0.layer_height            ) > EPSILON)
+                    return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
+                if (slicing_params.raft_layers() != slicing_params0.raft_layers())
+                    return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
+                if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
+                    return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
+                if (! equal_layering(slicing_params, slicing_params0))
+                    return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
+                if (has_custom_layering) {
+                    PrintObject::update_layer_height_profile(*object->model_object(), slicing_params, layer_height_profiles[i]);
+                    if (*(layer_height_profiles[i].end()-2) > *(layer_height_profiles[tallest_object_idx].end()-2))
+                        tallest_object_idx = i;
+                }
+            }
 
-                if (failed)
-                    return L("The Wipe tower is only supported if all objects have the same layer height profile");
+            if (has_custom_layering) {
+                const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
+                for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
+                    const PrintObject           *object               = m_objects[idx_object];
+                    const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
+                    bool                         failed               = false;
+                    if (layer_height_profile_tallest.size() >= layer_height_profile.size()) {
+                        int i = 0;
+                        while (i < layer_height_profile.size() && i < layer_height_profile_tallest.size()) {
+                            if (std::abs(layer_height_profile_tallest[i] - layer_height_profile[i])) {
+                                failed = true;
+                                break;
+                            }
+                            ++ i;
+                            if (i == layer_height_profile.size() - 2) // this element contains this objects max z
+                                if (layer_height_profile_tallest[i] > layer_height_profile[i]) // the difference does not matter in this case
+                                    ++ i;
+                        }
+                    } else
+                        failed = true;
+                    if (failed)
+                        return L("The Wipe tower is only supported if all objects have the same layer height profile");
+                }
             }
         }
     }
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index d0591e764..3de91818a 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -83,10 +83,6 @@ public:
     // vector of (vectors of volume ids), indexed by region_id
     std::vector<std::vector<int>> region_volumes;
 
-    // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
-    // The pairs of <z, layer_height> are packed into a 1D array.
-    std::vector<coordf_t>   layer_height_profile;
-    
     // this is set to true when LayerRegion->slices is split in top/internal/bottom
     // so that next call to make_perimeters() performs a union() before computing loops
     bool                    typed_slices;
@@ -175,7 +171,7 @@ private:
     void infill();
     void generate_support_material();
 
-    void _slice();
+    void _slice(const std::vector<coordf_t> &layer_height_profile);
     std::string _fix_slicing_errors();
     void _simplify_slices(double distance);
     void _make_perimeters();
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index 9dd101123..d516153a9 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -64,8 +64,6 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta
         }
         this->set_copies(copies);
     }
-
-    this->layer_height_profile = model_object->layer_height_profile;
 }
 
 PrintBase::ApplyStatus PrintObject::set_copies(const Points &points)
@@ -105,9 +103,10 @@ void PrintObject::slice()
     if (! this->set_started(posSlice))
         return;
     m_print->set_status(10, "Processing triangulated mesh");
-    this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), this->layer_height_profile);
+    std::vector<coordf_t> layer_height_profile;
+    this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), layer_height_profile);
     m_print->throw_if_canceled();
-    this->_slice();
+    this->_slice(layer_height_profile);
     m_print->throw_if_canceled();
     // Fix the model.
     //FIXME is this the right place to do? It is done repeateadly at the UI and now here at the backend.
@@ -1438,7 +1437,7 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
 // Resulting expolygons of layer regions are marked as Internal.
 //
 // this should be idempotent
-void PrintObject::_slice()
+void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
 {
     BOOST_LOG_TRIVIAL(info) << "Slicing objects..." << log_memory_info();
 
@@ -1457,7 +1456,7 @@ void PrintObject::_slice()
     {
         this->clear_layers();
         // Object layers (pairs of bottom/top Z coordinate), without the raft.
-        std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, this->layer_height_profile);
+        std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, layer_height_profile);
         // Reserve object layers for the raft. Last layer of the raft is the contact layer.
         int id = int(slicing_params.raft_layers());
         slice_zs.reserve(object_layers.size());
diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp
index 6477010fd..1d7858ead 100644
--- a/src/libslic3r/SLA/SLASupportTree.cpp
+++ b/src/libslic3r/SLA/SLASupportTree.cpp
@@ -738,45 +738,46 @@ public:
     const TriangleMesh& merged_mesh() const {
         if(meshcache_valid) return meshcache;
 
-        meshcache = TriangleMesh();
+        Contour3D merged;
 
         for(auto& head : heads()) {
             if(m_ctl.stopcondition()) break;
-            if(head.is_valid()) {
-                auto&& m = mesh(head.mesh);
-                meshcache.merge(m);
-            }
+            if(head.is_valid())
+                merged.merge(head.mesh);
         }
 
         for(auto& stick : pillars()) {
             if(m_ctl.stopcondition()) break;
-            meshcache.merge(mesh(stick.mesh));
-            meshcache.merge(mesh(stick.base));
+            merged.merge(stick.mesh);
+            merged.merge(stick.base);
         }
 
         for(auto& j : junctions()) {
             if(m_ctl.stopcondition()) break;
-            meshcache.merge(mesh(j.mesh));
+            merged.merge(j.mesh);
         }
 
         for(auto& cb : compact_bridges()) {
             if(m_ctl.stopcondition()) break;
-            meshcache.merge(mesh(cb.mesh));
+            merged.merge(cb.mesh);
         }
 
         for(auto& bs : bridges()) {
             if(m_ctl.stopcondition()) break;
-            meshcache.merge(mesh(bs.mesh));
+            merged.merge(bs.mesh);
         }
 
+
         if(m_ctl.stopcondition()) {
             // In case of failure we have to return an empty mesh
             meshcache = TriangleMesh();
             return meshcache;
         }
 
+        meshcache = mesh(merged);
+
         // TODO: Is this necessary?
-        meshcache.repair();
+        //meshcache.repair();
 
         BoundingBoxf3&& bb = meshcache.bounding_box();
         model_height = bb.max(Z) - bb.min(Z);
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 05bb07616..b02def988 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -45,7 +45,7 @@
 // Improves navigation between sidebar fields
 #define ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION (1 && ENABLE_1_42_0_ALPHA2)
 // Adds print bed models to 3D scene
-#define ENABLE_PRINT_BED_MODELS (0 && ENABLE_1_42_0_ALPHA2)
+#define ENABLE_PRINT_BED_MODELS (1 && ENABLE_1_42_0_ALPHA2)
 #endif // _technologies_h_
 
 
@@ -62,3 +62,5 @@
 #define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
 // Reworked management of bed shape changes
 #define ENABLE_REWORKED_BED_SHAPE_CHANGE (1 && ENABLE_1_42_0_ALPHA4)
+// Use anisotropic filtering on bed plate texture
+#define ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES (1 && ENABLE_1_42_0_ALPHA4)
diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp
index 8a0a087c0..ff8c20289 100644
--- a/src/libslic3r/TriangleMesh.cpp
+++ b/src/libslic3r/TriangleMesh.cpp
@@ -99,6 +99,8 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
     return *this;
 }
 
+// #define SLIC3R_TRACE_REPAIR
+
 void TriangleMesh::repair()
 {
     if (this->repaired) return;
@@ -109,7 +111,9 @@ void TriangleMesh::repair()
     BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() started";
     
     // checking exact
+#ifdef SLIC3R_TRACE_REPAIR
 	BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_exact";
+#endif /* SLIC3R_TRACE_REPAIR */
 	stl_check_facets_exact(&stl);
     stl.stats.facets_w_1_bad_edge = (stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge);
     stl.stats.facets_w_2_bad_edge = (stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge);
@@ -124,7 +128,9 @@ void TriangleMesh::repair()
         for (int i = 0; i < iterations; i++) {
             if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
                 //printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
+#ifdef SLIC3R_TRACE_REPAIR
 				BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_nearby";
+#endif /* SLIC3R_TRACE_REPAIR */
 				stl_check_facets_nearby(&stl, tolerance);
                 //printf("  Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
                 //last_edges_fixed = stl.stats.edges_fixed;
@@ -137,7 +143,9 @@ void TriangleMesh::repair()
     
     // remove_unconnected
     if (stl.stats.connected_facets_3_edge <  stl.stats.number_of_facets) {
+#ifdef SLIC3R_TRACE_REPAIR
         BOOST_LOG_TRIVIAL(trace) << "\tstl_remove_unconnected_facets";
+#endif /* SLIC3R_TRACE_REPAIR */
         stl_remove_unconnected_facets(&stl);
     }
     
@@ -146,26 +154,36 @@ void TriangleMesh::repair()
     // Don't fill holes, the current algorithm does more harm than good on complex holes.
     // Rather let the slicing algorithm close gaps in 2D slices.
     if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
+#ifdef SLIC3R_TRACE_REPAIR
         BOOST_LOG_TRIVIAL(trace) << "\tstl_fill_holes";
+#endif /* SLIC3R_TRACE_REPAIR */
         stl_fill_holes(&stl);
         stl_clear_error(&stl);
     }
 #endif
 
     // normal_directions
+#ifdef SLIC3R_TRACE_REPAIR
     BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_directions";
+#endif /* SLIC3R_TRACE_REPAIR */
     stl_fix_normal_directions(&stl);
 
     // normal_values
+#ifdef SLIC3R_TRACE_REPAIR
     BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_values";
+#endif /* SLIC3R_TRACE_REPAIR */
     stl_fix_normal_values(&stl);
     
     // always calculate the volume and reverse all normals if volume is negative
+#ifdef SLIC3R_TRACE_REPAIR
     BOOST_LOG_TRIVIAL(trace) << "\tstl_calculate_volume";
+#endif /* SLIC3R_TRACE_REPAIR */
     stl_calculate_volume(&stl);
     
     // neighbors
+#ifdef SLIC3R_TRACE_REPAIR
     BOOST_LOG_TRIVIAL(trace) << "\tstl_verify_neighbors";
+#endif /* SLIC3R_TRACE_REPAIR */
     stl_verify_neighbors(&stl);
 
     this->repaired = true;
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 0bd3d26ca..1a6c3b5b0 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -545,6 +545,11 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
     std::string model_path = resources_dir() + "/models/" + key;
 #endif // ENABLE_PRINT_BED_MODELS
 
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+    GLfloat max_anisotropy = 0.0f;
+    ::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+
     std::string filename = tex_path + "_top.png";
     if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
     {
@@ -553,6 +558,14 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
             _render_custom();
             return;
         }
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+        if (max_anisotropy > 0.0f)
+        {
+            ::glBindTexture(GL_TEXTURE_2D, m_top_texture.get_id());
+            ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+            ::glBindTexture(GL_TEXTURE_2D, 0);
+        }
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
     }
 
     filename = tex_path + "_bottom.png";
@@ -563,6 +576,14 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
             _render_custom();
             return;
         }
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+        if (max_anisotropy > 0.0f)
+        {
+            ::glBindTexture(GL_TEXTURE_2D, m_bottom_texture.get_id());
+            ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+            ::glBindTexture(GL_TEXTURE_2D, 0);
+        }
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
     }
 
 #if ENABLE_PRINT_BED_MODELS
@@ -570,7 +591,7 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
     {
         filename = model_path + "_bed.stl";
         if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs))
-            m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 1.0 + 0.5 * m_model.get_bounding_box().size()(2)));
+            m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2)));
 
         if (!m_model.get_filename().empty())
         {
@@ -1179,11 +1200,12 @@ void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
     m_layers_texture.valid = false;
 }
 
-void GLCanvas3D::LayersEditing::reset_layer_height_profile()
+void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
 {
 	const_cast<ModelObject*>(m_model_object)->layer_height_profile.clear();
     m_layer_height_profile.clear();
     m_layers_texture.valid = false;
+    canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
 }
 
 void GLCanvas3D::LayersEditing::generate_layer_height_texture()
@@ -5117,7 +5139,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             if (evt.LeftDown())
             {
                 // A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
-				m_layers_editing.reset_layer_height_profile();
+				m_layers_editing.reset_layer_height_profile(*this);
                 // Index 2 means no editing, just wait for mouse up event.
                 m_layers_editing.state = LayersEditing::Completed;
 
@@ -5251,7 +5273,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                         if (m_volumes.volumes[m_hover_volume_id]->hover && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower)
                         {
                             // forces the selection of the volume
-                            m_selection.add(m_hover_volume_id);
+                            if (!m_selection.is_multiple_full_instance())
+                                m_selection.add(m_hover_volume_id);
                             m_gizmos.update_on_off_state(m_selection);
                             post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
                             _update_gizmos_data();
@@ -5822,6 +5845,7 @@ void GLCanvas3D::set_camera_zoom(float zoom)
 void GLCanvas3D::update_gizmos_on_off_state()
 {
     set_as_dirty();
+    _update_gizmos_data();
     m_gizmos.update_on_off_state(get_selection());
 }
 
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 38f02ff8f..ab53d5048 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -360,7 +360,7 @@ class GLCanvas3D
 
 		void adjust_layer_height_profile();
 		void accept_changes(GLCanvas3D& canvas);
-        void reset_layer_height_profile();
+        void reset_layer_height_profile(GLCanvas3D& canvas);
 
         static float get_cursor_z_relative(const GLCanvas3D& canvas);
         static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp
index 1f37b7aec..2eba6f741 100644
--- a/src/slic3r/GUI/GLGizmo.cpp
+++ b/src/slic3r/GUI/GLGizmo.cpp
@@ -1511,7 +1511,7 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
     bool object_changed = m_model_object != model_object;
     m_model_object = model_object;
 
-    if (object_changed && is_plane_update_necessary())
+    if (model_object && (object_changed || is_plane_update_necessary()))
         update_planes();
 }
 
@@ -1585,15 +1585,17 @@ void GLGizmoFlatten::update_planes()
             m_planes.pop_back();
     }
 
+    // Let's prepare transformation of the normal vector from mesh to instance coordinates.
+    Geometry::Transformation t(inst_matrix);
+    Vec3d scaling = t.get_scaling_factor();
+    t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2)));
+
     // Now we'll go through all the polygons, transform the points into xy plane to process them:
     for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) {
         Pointf3s& polygon = m_planes[polygon_id].vertices;
         const Vec3d& normal = m_planes[polygon_id].normal;
 
-        // let's transform the normal accodring to the instance matrix:
-        Geometry::Transformation t(inst_matrix);
-        Vec3d scaling = t.get_scaling_factor();
-        t.set_scaling_factor(Vec3d(1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0))));
+        // transform the normal according to the instance matrix:
         Vec3d normal_transformed = t.get_matrix() * normal;
 
         // We are going to rotate about z and y to flatten the plane
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 9991fee75..462f3c328 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -194,6 +194,8 @@ bool GUI_App::OnInit()
             preset_updater->slic3r_update_notify();
         }
         preset_updater->sync(preset_bundle);
+
+        load_current_presets();
     });
 
 
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 3426fd02a..a880b2cbe 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -51,6 +51,7 @@ ObjectList::ObjectList(wxWindow* parent) :
     create_object_popupmenu(&m_menu_object);
     create_part_popupmenu(&m_menu_part);
     create_sla_object_popupmenu(&m_menu_sla_object);
+    create_instance_popupmenu(&m_menu_instance);
 
     // describe control behavior 
     Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
@@ -97,7 +98,7 @@ void ObjectList::create_objects_ctrl()
     // temporary workaround for the correct behavior of the Scrolled sidebar panel:
     // 1. set a height of the list to some big value 
     // 2. change it to the normal min value (200) after first whole App updating/layouting
-    SetMinSize(wxSize(-1, 1500));   // #ys_FIXME 
+    SetMinSize(wxSize(-1, 3000));   // #ys_FIXME 
 
     m_sizer = new wxBoxSizer(wxVERTICAL);
     m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);
@@ -400,15 +401,28 @@ void ObjectList::OnContextMenu(wxDataViewEvent&)
 
 void ObjectList::show_context_menu()
 {
+    if (multiple_selection() && selected_instances_of_same_object())
+    {
+        wxGetApp().plater()->PopupMenu(&m_menu_instance);
+
+        wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
+            evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
+        return;
+    }
+
     const auto item = GetSelection();
     if (item)
     {
-        if (!(m_objects_model->GetItemType(item) & (itObject | itVolume)))
+        const ItemType type = m_objects_model->GetItemType(item);
+        if (!(type & (itObject | itVolume | itInstance)))
             return;
-        wxMenu* menu = m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
+
+        wxMenu* menu = type & itInstance ? &m_menu_instance :
+                       m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
                        wxGetApp().plater()->printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
 
-        append_menu_item_settings(menu);
+        if (!(type & itInstance))
+            append_menu_item_settings(menu);
 
         wxGetApp().plater()->PopupMenu(menu);
 
@@ -443,15 +457,35 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
 {
     const wxDataViewItem item(event.GetItem());
 
-    // only allow drags for item, not containers
-    if (multiple_selection() || GetSelection()!=item || 
-        m_objects_model->GetParent(item) == wxDataViewItem(0) ||
-        m_objects_model->GetItemType(item) != itVolume ) {
+    const bool mult_sel = multiple_selection();
+
+    if (mult_sel && !selected_instances_of_same_object() ||
+        !mult_sel && (GetSelection() != item ||
+        m_objects_model->GetParent(item) == wxDataViewItem(0) ) ) {
+        event.Veto();
+        return;
+    }
+   
+    const ItemType& type = m_objects_model->GetItemType(item);
+    if (!(type & (itVolume | itInstance))) {
         event.Veto();
         return;
     }
 
-    m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), m_objects_model->GetVolumeIdByItem(item));
+    if (mult_sel)
+    {
+        m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),type);
+        std::set<int>& sub_obj_idxs = m_dragged_data.inst_idxs();
+        wxDataViewItemArray sels;
+        GetSelections(sels);
+        for (auto sel : sels )
+            sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel));
+    }
+    else 
+        m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), 
+                        type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
+                                        m_objects_model->GetInstanceIdByItem(item), 
+                        type);
 
     /* Under MSW or OSX, DnD moves an item to the place of another selected item
     * But under GTK, DnD moves an item between another two items.
@@ -470,31 +504,41 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
     event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move;
 }
 
+bool ObjectList::can_drop(const wxDataViewItem& item) const 
+{
+    return  m_dragged_data.type() == itInstance && !item.IsOk()     ||
+            m_dragged_data.type() == itVolume && item.IsOk() &&
+            m_objects_model->GetItemType(item) == itVolume &&
+            m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item);
+}
+
 void ObjectList::OnDropPossible(wxDataViewEvent &event)
 {
-    wxDataViewItem item(event.GetItem());
+    const wxDataViewItem& item = event.GetItem();
 
-    // only allow drags for item or background, not containers
-    if (!item.IsOk() ||
-        m_objects_model->GetParent(item) == wxDataViewItem(0) || 
-        m_objects_model->GetItemType(item) != itVolume ||
-        m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item))
+    if (!can_drop(item))
         event.Veto();
 }
 
 void ObjectList::OnDrop(wxDataViewEvent &event)
 {
-    wxDataViewItem item(event.GetItem());
+    const wxDataViewItem& item = event.GetItem();
 
-    if (!item.IsOk() || m_objects_model->GetParent(item) == wxDataViewItem(0) ||
-                        m_objects_model->GetItemType(item) != itVolume ||
-                        m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item)) {
+    if (!can_drop(item))
+    {
         event.Veto();
         m_dragged_data.clear();
         return;
     }
 
-    const int from_volume_id = m_dragged_data.vol_idx();
+    if (m_dragged_data.type() == itInstance)
+    {
+        instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs());
+        m_dragged_data.clear();
+        return;
+    }
+
+    const int from_volume_id = m_dragged_data.sub_obj_idx();
     int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
 
 // It looks like a fixed in current version of the wxWidgets
@@ -506,7 +550,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
 //     if (to_volume_id > from_volume_id) to_volume_id--;
 // #endif // __WXGTK__
 
-    auto& volumes = (*m_objects)[/*m_selected_object_id*/m_dragged_data.obj_idx()]->volumes;
+    auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
     auto delta = to_volume_id < from_volume_id ? -1 : 1;
     int cnt = 0;
     for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
@@ -516,7 +560,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
                                                     m_objects_model->GetParent(item)));
 
     m_parts_changed = true;
-    parts_changed(/*m_selected_object_id*/m_dragged_data.obj_idx());
+    parts_changed(m_dragged_data.obj_idx());
 
     m_dragged_data.clear();
 }
@@ -741,6 +785,12 @@ wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu)
 
 }
 
+wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
+{
+    return append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")), "",
+        [this](wxCommandEvent&) { split_instances(); }, "", menu);
+}
+
 void ObjectList::create_object_popupmenu(wxMenu *menu)
 {
     append_menu_items_add_volume(menu);
@@ -769,6 +819,11 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
     menu->AppendSeparator();
 }
 
+void ObjectList::create_instance_popupmenu(wxMenu*menu)
+{
+    m_menu_item_split_instances = append_menu_item_instance_to_object(menu);
+}
+
 wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
 {
     wxMenu *menu = new wxMenu;
@@ -1116,6 +1171,27 @@ bool ObjectList::is_splittable()
     return splittable;
 }
 
+bool ObjectList::selected_instances_of_same_object()
+{
+    wxDataViewItemArray sels;
+    GetSelections(sels);
+
+    const int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
+
+    for (auto item : sels) {
+        if (! (m_objects_model->GetItemType(item) & itInstance) ||
+            obj_idx != m_objects_model->GetObjectIdByItem(item))
+            return false;
+    }
+    return true;
+}
+
+bool ObjectList::can_split_instances()
+{
+    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    return selection.is_multiple_full_instance() || selection.is_single_full_instance();
+}
+
 void ObjectList::part_settings_changed()
 {
     m_part_settings_changed = true;
@@ -1419,7 +1495,7 @@ bool ObjectList::multiple_selection() const
 
 void ObjectList::update_selections()
 {
-    auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     wxDataViewItemArray sels;
 
     // We doesn't update selection if SettingsItem for the current object/part is selected
@@ -1505,7 +1581,7 @@ void ObjectList::update_selections()
 
 void ObjectList::update_selections_on_canvas()
 {
-    auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
 
     const int sel_cnt = GetSelectedItemsCount();
     if (sel_cnt == 0) {
@@ -1729,6 +1805,43 @@ void ObjectList::update_settings_items()
     UnselectAll();
 }
 
+void ObjectList::instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idxs)
+{
+    // create new object from selected instance  
+    ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
+    for (int inst_idx = model_object->instances.size() - 1; inst_idx >= 0; inst_idx--)
+    {
+        if (find(inst_idxs.begin(), inst_idxs.end(), inst_idx) != inst_idxs.end())
+            continue;
+        model_object->delete_instance(inst_idx);
+    }
+
+    // Add new object to the object_list
+    add_object_to_list(m_objects->size() - 1);
+
+    for (std::set<int>::const_reverse_iterator it = inst_idxs.rbegin(); it != inst_idxs.rend(); ++it)
+    {
+        // delete selected instance from the object
+        del_subobject_from_object(obj_idx, *it, itInstance);
+        delete_instance_from_list(obj_idx, *it);
+    }
+}
+
+void ObjectList::split_instances()
+{
+    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const int obj_idx = selection.get_object_idx();
+    if (obj_idx == -1)
+        return;
+
+    const int inst_idx = selection.get_instance_idx();
+    const std::set<int> inst_idxs = inst_idx < 0 ?
+                                    selection.get_instance_idxs() :
+                                    std::set<int>{ inst_idx };
+
+    instances_to_separated_object(obj_idx, inst_idxs);
+}
+
 void ObjectList::ItemValueChanged(wxDataViewEvent &event)
 {
     if (event.GetColumn() == 0)
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index 7631782df..f24eb95b0 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -56,22 +56,38 @@ class ObjectList : public wxDataViewCtrl
 
     struct dragged_item_data
     {
-        void init(const int obj_idx, const int vol_idx) {
+        void init(const int obj_idx, const int subobj_idx, const ItemType type) {
             m_obj_idx = obj_idx;
-            m_vol_idx = vol_idx;            
+            m_type = type;
+            if (m_type&itVolume)
+                m_vol_idx = subobj_idx;
+            else
+                m_inst_idxs.insert(subobj_idx);
+        }
+
+        void init(const int obj_idx, const ItemType type) {
+            m_obj_idx = obj_idx;
+            m_type = type;
         }
 
         void clear() {
             m_obj_idx = -1;
-            m_vol_idx = -1;            
+            m_vol_idx = -1;
+            m_inst_idxs.clear();
+            m_type = itUndef;
         }
 
         int obj_idx() const  { return m_obj_idx; }
-        int vol_idx() const  { return m_vol_idx; }
+        int sub_obj_idx() const  { return m_vol_idx; }
+        ItemType type() const { return m_type; }
+        std::set<int>& inst_idxs() { return m_inst_idxs; }
 
     private:
         int m_obj_idx = -1;
         int m_vol_idx = -1;
+        std::set<int> m_inst_idxs{};
+        ItemType m_type = itUndef;
+
     } m_dragged_data;
 
     wxBoxSizer          *m_sizer {nullptr};
@@ -91,9 +107,11 @@ class ObjectList : public wxDataViewCtrl
     wxMenu      m_menu_object;
     wxMenu      m_menu_part;
     wxMenu      m_menu_sla_object;
+    wxMenu      m_menu_instance;
     wxMenuItem* m_menu_item_split { nullptr };
     wxMenuItem* m_menu_item_split_part { nullptr };
     wxMenuItem* m_menu_item_settings { nullptr };
+    wxMenuItem* m_menu_item_split_instances { nullptr };
 
     std::vector<wxBitmap*> m_bmp_vector;
 
@@ -148,9 +166,11 @@ public:
     wxMenuItem*         append_menu_item_split(wxMenu* menu);
     wxMenuItem*         append_menu_item_settings(wxMenu* menu);
     wxMenuItem*         append_menu_item_change_type(wxMenu* menu);
+    wxMenuItem*         append_menu_item_instance_to_object(wxMenu* menu);
     void                create_object_popupmenu(wxMenu *menu);
     void                create_sla_object_popupmenu(wxMenu*menu);
     void                create_part_popupmenu(wxMenu*menu);
+    void                create_instance_popupmenu(wxMenu*menu);
     wxMenu*             create_settings_popupmenu(wxMenu *parent_menu);
 
     void                update_opt_keys(t_config_option_keys& t_optopt_keys);
@@ -166,6 +186,8 @@ public:
     void                split();
     bool                get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume);
     bool                is_splittable();
+    bool                selected_instances_of_same_object();
+    bool                can_split_instances();
 
     wxPoint             get_mouse_position_in_control();
     wxBoxSizer*         get_sizer() {return  m_sizer;}
@@ -222,6 +244,9 @@ public:
     bool has_multi_part_objects();
     void update_settings_items();
 
+    void instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idx);
+    void split_instances();
+
 private:
     void OnChar(wxKeyEvent& event);
     void OnContextMenu(wxDataViewEvent &event);
@@ -229,6 +254,7 @@ private:
     void OnBeginDrag(wxDataViewEvent &event);
     void OnDropPossible(wxDataViewEvent &event);
     void OnDrop(wxDataViewEvent &event);
+    bool can_drop(const wxDataViewItem& item) const ;
 
     void ItemValueChanged(wxDataViewEvent &event);
     void OnEditingDone(wxDataViewEvent &event);
diff --git a/src/slic3r/GUI/I18N.hpp b/src/slic3r/GUI/I18N.hpp
index c86ff7501..a899eaa59 100644
--- a/src/slic3r/GUI/I18N.hpp
+++ b/src/slic3r/GUI/I18N.hpp
@@ -2,6 +2,10 @@
 #define _(s)    Slic3r::GUI::I18N::translate((s))
 #endif /* _ */
 
+#ifndef _CTX
+#define _CTX(s, ctx) Slic3r::GUI::I18N::translate((s), (ctx))
+#endif /* _ */
+
 #ifndef L
 // !!! If you needed to translate some wxString,
 // !!! please use _(L(string))
@@ -21,6 +25,7 @@
 #define slic3r_GUI_I18N_hpp_
 
 #include <wx/intl.h>
+#include <wx/version.h>
 
 namespace Slic3r { namespace GUI { 
 
@@ -29,7 +34,20 @@ namespace I18N {
 	inline wxString translate(const wchar_t *s) 	 { return wxGetTranslation(s); }
 	inline wxString translate(const std::string &s)  { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)); }
 	inline wxString translate(const std::wstring &s) { return wxGetTranslation(s.c_str()); }
-} 
+
+#if wxCHECK_VERSION(3, 1, 1)
+	#define _wxGetTranslation_ctx(S, CTX) wxGetTranslation((S), wxEmptyString, (CTX))
+#else
+	#define _wxGetTranslation_ctx(S, CTX) ((void)(CTX), wxGetTranslation((S)))
+#endif
+
+	inline wxString translate(const char *s, const char* ctx)         { return _wxGetTranslation_ctx(wxString(s, wxConvUTF8), ctx); }
+	inline wxString translate(const wchar_t *s, const char* ctx)      { return _wxGetTranslation_ctx(s, ctx); }
+	inline wxString translate(const std::string &s, const char* ctx)  { return _wxGetTranslation_ctx(wxString(s.c_str(), wxConvUTF8), ctx); }
+	inline wxString translate(const std::wstring &s, const char* ctx) { return _wxGetTranslation_ctx(s.c_str(), ctx); }
+
+#undef _wxGetTranslation_ctx
+}
 
 // Return translated std::string as a wxString
 wxString	L_str(const std::string &str);
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 9c74861c9..46a46e950 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -155,7 +155,6 @@ void MainFrame::create_preset_tabs()
     add_created_tab(new TabSLAPrint(m_tabpanel));
     add_created_tab(new TabSLAMaterial(m_tabpanel));
     add_created_tab(new TabPrinter(m_tabpanel));
-    GUI::wxGetApp().load_current_presets();
 }
 
 void MainFrame::add_created_tab(Tab* panel)
diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp
index 4952398f3..78bbe4fec 100644
--- a/src/slic3r/GUI/OptionsGroup.cpp
+++ b/src/slic3r/GUI/OptionsGroup.cpp
@@ -234,7 +234,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText**	full_Label/* = n
 // 			wxString str_label = _(option.label);
 //!			To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
 			wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
-								wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label)) :
+								_CTX(option.label, "Layers") :
 								_(option.label);
 			label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
 			label->SetFont(label_font);
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index ac4988a6c..37b55d89f 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1063,6 +1063,7 @@ private:
     bool can_delete_object() const;
     bool can_increase_instances() const;
     bool can_decrease_instances() const;
+    bool can_set_instance_to_object() const;
     bool can_split_to_objects() const;
     bool can_split_to_volumes() const;
     bool can_split() const;
@@ -2365,11 +2366,16 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
             [this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
         wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
             [this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
+
+        menu->AppendSeparator();
+        wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu);
+
         if (q != nullptr)
         {
             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());
             q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_set_number_of_copies->GetId());
+            q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_set_instance_to_object()); }, item_instance_to_object->GetId());
         }
         menu->AppendSeparator();
 
@@ -2432,9 +2438,9 @@ bool Plater::priv::complit_init_object_menu()
     // ui updates needs to be binded to the parent panel
     if (q != nullptr)
     {
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects() || can_split_to_volumes*/()); }, item_split->GetId());
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects*/()); }, item_split_objects->GetId());
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_volumes*/()); }, item_split_volumes->GetId());
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId());
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split_objects->GetId());
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split_volumes->GetId());
     }
     return true;
 }
@@ -2453,7 +2459,7 @@ bool Plater::priv::complit_init_sla_object_menu()
     // ui updates needs to be binded to the parent panel
     if (q != nullptr)
     {
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects*/()); }, item_split->GetId());
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId());
     }
 
     return true;
@@ -2472,7 +2478,7 @@ bool Plater::priv::complit_init_part_menu()
     // ui updates needs to be binded to the parent panel
     if (q != nullptr)
     {
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_volumes*/()); },  item_split->GetId());
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); },  item_split->GetId());
     }
 
     return true;
@@ -2540,6 +2546,12 @@ bool Plater::priv::can_increase_instances() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
 }
 
+bool Plater::priv::can_set_instance_to_object() const
+{
+    const int obj_idx = get_selected_object_idx();
+    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
+}
+
 bool Plater::priv::can_decrease_instances() const
 {
     int obj_idx = get_selected_object_idx();
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 52eb3180d..55c0b351f 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -406,7 +406,7 @@ void PrusaObjectDataViewModelNode::set_object_action_icon() {
 	m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("add_object.png")), wxBITMAP_TYPE_PNG);
 }
 void  PrusaObjectDataViewModelNode::set_part_action_icon() {
-	m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG);
+	m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(m_type == itVolume ? "cog.png" : "brick_go.png")), wxBITMAP_TYPE_PNG);
 }
 
 Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index fcce18e10..10709786c 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -275,6 +275,7 @@ public:
         else if (type == itInstance) {
             m_idx = parent->GetChildCount();
             m_name = wxString::Format("Instance_%d", m_idx+1);
+            set_part_action_icon();
         }
 	}
 
diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp
index aa90a3ad9..b8662dcd8 100644
--- a/xs/xsp/Print.xsp
+++ b/xs/xsp/Print.xsp
@@ -49,8 +49,6 @@ _constant()
     Ref<StaticPrintConfig> config()
         %code%{ RETVAL = &THIS->config(); %};
     Points copies();
-    std::vector<double> layer_height_profile()
-        %code%{ RETVAL = THIS->layer_height_profile; %};
     Clone<BoundingBox> bounding_box();
     
     Points _shifted_copies()