diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 743ac19b4..53066d708 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -58,7 +58,7 @@ ObjectList::ObjectList(wxWindow* parent) :
     Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); });
 
     GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) {
-        set_tooltip_for_item(event.GetPosition());
+        set_tooltip_for_item(/*event.GetPosition()*/get_mouse_position_in_control());
         event.Skip();
     });
 #else
@@ -94,17 +94,13 @@ void ObjectList::create_objects_ctrl()
     // column 0(Icon+Text) of the view control: 
     // And Icon can be consisting of several bitmaps
     AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(),
-        0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
+        0, 250, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
 
     // column 1 of the view control:
-    AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45,
-        wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
-
-    // column 2 of the view control:
     AppendColumn(create_objects_list_extruder_column(4));
 
-    // column 3 of the view control:
-    AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25,
+    // column 2 of the view control:
+    AppendBitmapColumn(" ", 2, wxDATAVIEW_CELL_INERT, 25,
         wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
 }
 
@@ -118,7 +114,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt)
     if (col->GetTitle() == " " && GetSelectedItemsCount()<2)
         GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings")));
     else if (col->GetTitle() == _("Name") &&
-        m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) {
+        m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) {
         int obj_idx = m_objects_model->GetIdByItem(item);
         auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats;
         int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
@@ -178,7 +174,7 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_
         choices.Add(wxString::Format("%d", i));
     wxDataViewChoiceRenderer *c =
         new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL);
-    wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 2, 60, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
+    wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 1, 80, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
     return column;
 }
 
@@ -188,17 +184,17 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count)
     if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA)
         extruders_count = 1;
 
-    // delete old 3rd column
-    DeleteColumn(GetColumn(2));
+    // delete old 2nd column
+    DeleteColumn(GetColumn(1));
     // insert new created 3rd column
-    InsertColumn(2, create_objects_list_extruder_column(extruders_count));
+    InsertColumn(1, create_objects_list_extruder_column(extruders_count));
     // set show/hide for this column 
     set_extruder_column_hidden(extruders_count <= 1);
 }
 
 void ObjectList::set_extruder_column_hidden(bool hide)
 {
-    GetColumn(2)->SetHidden(hide);
+    GetColumn(1)->SetHidden(hide);
 }
 
 void ObjectList::update_extruder_in_config(const wxString& selection)
@@ -214,11 +210,11 @@ void ObjectList::update_extruder_in_config(const wxString& selection)
 }
 
 void ObjectList::init_icons(){
-    m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
-    m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
+    m_bmp_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
+    m_bmp_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
 
     // init icon for manifold warning
-    m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
+    m_bmp_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
 
     // init bitmap for "Split to sub-objects" context menu
     m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG);
@@ -268,7 +264,7 @@ void ObjectList::context_menu()
         show_context_menu();
 
         else if (title == _("Name") && pt.x >15 &&
-                    m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData())
+                    m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData())
         {
             if (is_windows10())
                 /*fix_through_netfabb()*/;// #ys_FIXME
@@ -283,7 +279,7 @@ void ObjectList::show_context_menu()
     const auto item = GetSelection();
     if (item)
     {
-        if (m_objects_model->IsSettingsItem(item))
+        if (!(m_objects_model->GetItemType(item) & (itObject | itVolume)))
             return;
         const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ?
             create_add_part_popupmenu() :
@@ -313,10 +309,10 @@ void ObjectList::key_event(wxKeyEvent& event)
 
 void ObjectList::item_value_change(wxDataViewEvent& event)
 {
-    if (event.GetColumn() == 2)
+    if (event.GetColumn() == 1)
     {
         wxVariant variant;
-        m_objects_model->GetValue(variant, event.GetItem(), 2);
+        m_objects_model->GetValue(variant, event.GetItem(), 1);
 #ifdef __WXOSX__
         m_selected_extruder = variant.GetString();
 #else // --> for Linux
@@ -325,14 +321,20 @@ void ObjectList::item_value_change(wxDataViewEvent& event)
     }
 }
 
+struct draging_item_data
+{
+    int obj_idx;
+    int vol_idx;
+};
+
 void ObjectList::on_begin_drag(wxDataViewEvent &event)
 {
     wxDataViewItem item(event.GetItem());
 
     // only allow drags for item, not containers
     if (multiple_selection() ||
-        m_objects_model->GetParent(item) == wxDataViewItem(0) || 
-        m_objects_model->IsSettingsItem(item) ) {
+        m_objects_model->GetParent(item) == wxDataViewItem(0) ||
+        m_objects_model->GetItemType(item) != itVolume ) {
         event.Veto();
         return;
     }
@@ -356,7 +358,7 @@ void ObjectList::on_drop_possible(wxDataViewEvent &event)
 
     // only allow drags for item or background, not containers
     if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
-        event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item))
+        event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume)
         event.Veto();
 }
 
@@ -366,7 +368,7 @@ void ObjectList::on_drop(wxDataViewEvent &event)
 
     // only allow drops for item, not containers
     if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
-        event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) {
+        event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume) {
         event.Veto();
         return;
     }
@@ -495,7 +497,7 @@ void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part)
     // Add settings item for object
     const auto item = GetSelection();
     if (item) {
-        const auto settings_item = m_objects_model->HasSettings(item);
+        const auto settings_item = m_objects_model->GetSettingsItem(item);
         select_item(settings_item ? settings_item :
             m_objects_model->AddSettingsChild(item));
 #ifndef __WXOSX__
@@ -547,7 +549,7 @@ wxMenu* ObjectList::create_add_part_popupmenu()
     int i = 0;
     for (auto& item : menu_items) {
         auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item));
-        menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh);
+        menu_item->SetBitmap(i == 0 ? m_bmp_solidmesh : m_bmp_modifiermesh);
         if (item == "Add generic")
             menu_item_add_generic(menu_item, config_id_base + i);
         menu->Append(menu_item);
@@ -666,8 +668,8 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* =
     parts_changed(obj_idx);
 
     for (int i = 0; i < part_names.size(); ++i) {
-        const wxDataViewItem sel_item = m_objects_model->AddChild(item, part_names.Item(i),
-            is_modifier ? m_icon_modifiermesh : m_icon_solidmesh);
+        const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i),
+            is_modifier ? m_bmp_modifiermesh : m_bmp_solidmesh);
 
         if (i == part_names.size() - 1)
             select_item(sel_item);
@@ -816,8 +818,8 @@ void ObjectList::load_lambda(const std::string& type_name)
     m_parts_changed = true;
     parts_changed(m_selected_object_id);
 
-    select_item(m_objects_model->AddChild(GetSelection(),
-        name, m_icon_modifiermesh));
+    select_item(m_objects_model->AddVolumeChild(GetSelection(),
+        name, m_bmp_modifiermesh));
 #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
     selection_changed();
 #endif //no __WXOSX__ //__WXMSW__
@@ -830,15 +832,20 @@ void ObjectList::del_subobject_item(wxDataViewItem& item)
 {
     if (!item) return;
 
-    int obj_idx, vol_idx;
-    m_objects_model->GetObjectAndVolumeIdsByItem(item, obj_idx, vol_idx);
+    int obj_idx, idx;
+    ItemType type;
 
-    if (vol_idx == -1)
+    m_objects_model->GetItemInfo(item, type, obj_idx, idx);
+    if (type == itUndef)
         return;
 
-    if (vol_idx == -2)
+    if (type == itSettings)
         del_settings_from_config();
-    else if (!del_subobject_from_object(obj_idx, vol_idx))
+    else if (type == itInstanceRoot && obj_idx != -1)
+        del_instances_from_object(obj_idx);
+    else if (idx == -1)
+        return;
+    else if (!del_subobject_from_object(obj_idx, idx, type))
         return;
 
     m_objects_model->Delete(item);
@@ -859,21 +866,48 @@ void ObjectList::del_settings_from_config()
         m_config->set_key_value("extruder", new ConfigOptionInt(extruder));
 }
 
-bool ObjectList::del_subobject_from_object(const int obj_idx, const int vol_idx)
+void ObjectList::del_instances_from_object(const int obj_idx)
 {
-    const auto volume = (*m_objects)[obj_idx]->volumes[vol_idx];
+    auto instances = (*m_objects)[obj_idx]->instances;
+    if (instances.size() <= 1)
+        return;
 
-    // if user is deleting the last solid part, throw error
-    int solid_cnt = 0;
-    for (auto vol : (*m_objects)[obj_idx]->volumes)
-        if (vol->is_model_part())
-            ++solid_cnt;
-    if (volume->is_model_part() && solid_cnt == 1) {
-        Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
-        return false;
+    while ( instances.size()> 1)
+        instances.pop_back();
+
+    (*m_objects)[obj_idx]->invalidate_bounding_box(); // ? #ys_FIXME
+
+    m_parts_changed = true;
+    parts_changed(obj_idx);
+}
+
+bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type)
+{
+    if (type == itVolume) {
+        const auto volume = (*m_objects)[obj_idx]->volumes[idx];
+
+        // if user is deleting the last solid part, throw error
+        int solid_cnt = 0;
+        for (auto vol : (*m_objects)[obj_idx]->volumes)
+            if (vol->is_model_part())
+                ++solid_cnt;
+        if (volume->is_model_part() && solid_cnt == 1) {
+            Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from object.")));
+            return false;
+        }
+
+        (*m_objects)[obj_idx]->delete_volume(idx);
     }
+    else if (type == itInstance) {
+        if ((*m_objects)[obj_idx]->instances.size() == 1) {
+            Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object.")));
+            return false;
+        }
+        (*m_objects)[obj_idx]->delete_instance(idx);
+    }
+    else
+        return false;
 
-    (*m_objects)[obj_idx]->delete_volume(vol_idx);
     m_parts_changed = true;
     parts_changed(obj_idx);
 
@@ -901,8 +935,8 @@ void ObjectList::split(const bool split_part)
         m_objects_model->DeleteChildren(parent);
 
         for (auto id = 0; id < model_object->volumes.size(); id++)
-            m_objects_model->AddChild(parent, model_object->volumes[id]->name,
-            model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh,
+            m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name,
+            model_object->volumes[id]->is_modifier() ? m_bmp_modifiermesh : m_bmp_solidmesh,
             model_object->volumes[id]->config.has("extruder") ?
             model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
             false);
@@ -911,8 +945,8 @@ void ObjectList::split(const bool split_part)
     }
     else {
         for (auto id = 0; id < model_object->volumes.size(); id++)
-            m_objects_model->AddChild(item, model_object->volumes[id]->name,
-            m_icon_solidmesh,
+            m_objects_model->AddVolumeChild(item, model_object->volumes[id]->name,
+            m_bmp_solidmesh,
             model_object->volumes[id]->config.has("extruder") ?
             model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
             false);
@@ -1001,7 +1035,7 @@ void ObjectList::part_selection_changed()
                     m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
                 }
             }
-            else {
+            else if (m_objects_model->GetItemType(item) == itVolume){
                 og_name = _(L("Part manipulation"));
                 is_part = true;
                 const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
@@ -1038,7 +1072,7 @@ void ObjectList::add_object_to_list(size_t obj_idx)
 {
     auto model_object = (*m_objects)[obj_idx];
     wxString item_name = model_object->name;
-    auto item = m_objects_model->Add(item_name, model_object->instances.size());
+    auto item = m_objects_model->Add(item_name);
 #if !ENABLE_EXTENDED_SELECTION
     /*Select*/select_item(item);
 #endif // !ENABLE_EXTENDED_SELECTION
@@ -1049,15 +1083,15 @@ void ObjectList::add_object_to_list(size_t obj_idx)
         stats.facets_added + stats.facets_reversed + stats.backwards_edges;
     if (errors > 0)		{
         wxVariant variant;
-        variant << PrusaDataViewBitmapText(item_name, m_icon_manifold_warning);
+        variant << PrusaDataViewBitmapText(item_name, m_bmp_manifold_warning);
         m_objects_model->SetValue(variant, item, 0);
     }
 
     if (model_object->volumes.size() > 1) {
         for (auto id = 0; id < model_object->volumes.size(); id++)
-            m_objects_model->AddChild(item,
+            m_objects_model->AddVolumeChild(item,
             model_object->volumes[id]->name,
-            m_icon_solidmesh,
+            m_bmp_solidmesh,
             model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
             false);
         Expand(item);
@@ -1095,10 +1129,14 @@ void ObjectList::delete_all_objects_from_list()
     part_selection_changed();
 }
 
-void ObjectList::set_object_count(int idx, int count)
+void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num)
 {
-    m_objects_model->SetValue(wxString::Format("%d", count), idx, 1);
-    Refresh();
+    select_item(m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num));
+}
+
+void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t num)
+{
+    select_item(m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num));
 }
 
 void ObjectList::unselect_objects()
@@ -1198,15 +1236,21 @@ void ObjectList::update_selections_on_canvas()
             return;
         }
 
-        auto parent = m_objects_model->GetParent(item);
-        const int obj_idx = m_objects_model->GetIdByItem(parent);
-        const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
-        selection.add_volume(obj_idx, vol_idx, as_single_selection);        
+        if (m_objects_model->GetItemType(item) == itVolume) {
+            const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item));
+            const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
+            selection.add_volume(obj_idx, vol_idx, as_single_selection);
+        }
+        else if (m_objects_model->GetItemType(item) == itInstance) {
+            const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
+            const int inst_idx = m_objects_model->GetInstanceIdByItem(item);
+            selection.add_instance(obj_idx, inst_idx, as_single_selection);
+        }
     };
 
     if (sel_cnt == 1) {
         wxDataViewItem item = GetSelection();
-        if (m_objects_model->IsSettingsItem(item))
+        if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot))
             add_to_selection(m_objects_model->GetParent(item), selection, true);
         else
             add_to_selection(item, selection, true);
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index 21b4a729f..c56e69670 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -22,9 +22,9 @@ class ObjectList : public wxDataViewCtrl
 
     DynamicPrintConfig  *m_default_config {nullptr};
 
-    wxBitmap	m_icon_modifiermesh;
-    wxBitmap	m_icon_solidmesh;
-    wxBitmap	m_icon_manifold_warning;
+    wxBitmap	m_bmp_modifiermesh;
+    wxBitmap	m_bmp_solidmesh;
+    wxBitmap	m_bmp_manifold_warning;
     wxBitmap	m_bmp_cog;
     wxBitmap	m_bmp_split;
 
@@ -87,7 +87,8 @@ public:
     void                load_lambda(const std::string& type_name);
     void                del_subobject_item(wxDataViewItem& item);
     void                del_settings_from_config();
-    bool                del_subobject_from_object(const int obj_idx, const int vol_idx);
+    void                del_instances_from_object(const int obj_idx);
+    bool                del_subobject_from_object(const int obj_idx, const int idx, const int type);
     void                split(const bool split_part);
     bool                get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume);
     bool                is_splittable_object(const bool split_part);
@@ -111,8 +112,10 @@ public:
     void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx);
     // Delete all objects from the list
     void delete_all_objects_from_list();
-    // Set count of object on c++ side
-    void set_object_count(int idx, int count);
+    // Increase instances count
+    void increase_object_instances(const size_t obj_idx, const size_t num);
+    // Decrease instances count
+    void decrease_object_instances(const size_t obj_idx, const size_t num);
 
     // #ys_FIXME_to_delete
     // Unselect all objects in the list on c++ side
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 1015e783c..04201b709 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -30,11 +30,11 @@ class Tab;
 
 enum QuickSlice
 {
-    qsUndef,
-    qsReslice,
-    qsSaveAs,
-    qsExportSVG,
-    qsExportPNG
+    qsUndef = 0,
+    qsReslice = 1,
+    qsSaveAs = 2,
+    qsExportSVG = 4,
+    qsExportPNG = 8
 };
 
 struct PresetTab {
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index c58f02f83..051b05598 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1952,7 +1952,7 @@ void Plater::increase(size_t num)
     float offset = 10.0;
     for (size_t i = 0; i < num; i++, offset += 10.0) {
         Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0);
-        auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation());
+        model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation());
 #if ENABLE_EXTENDED_SELECTION
         p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec));
 #else
@@ -1961,9 +1961,9 @@ void Plater::increase(size_t num)
     }
 
 #if ENABLE_EXTENDED_SELECTION
-    sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size());
+    sidebar().obj_list()->increase_object_instances(obj_idx, num);
 #else
-    sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size());
+    sidebar().obj_list()->increase_object_instances(*obj_idx, num);
 #endif // ENABLE_EXTENDED_SELECTION
 
     if (p->get_config("autocenter") == "1") {
@@ -2001,9 +2001,9 @@ void Plater::decrease(size_t num)
 #endif // ENABLE_EXTENDED_SELECTION
         }
 #if ENABLE_EXTENDED_SELECTION
-        sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size());
+        sidebar().obj_list()->decrease_object_instances(obj_idx, num);
 #else
-        sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size());
+        sidebar().obj_list()->decrease_object_instances(*obj_idx, num);
 #endif // ENABLE_EXTENDED_SELECTION
     }
     else {
@@ -2285,6 +2285,7 @@ void Plater::changed_object_settings(int obj_idx)
         _3DScene::set_objects_selections(p->canvas3D, selections);
 #endif // !ENABLE_EXTENDED_SELECTION
         _3DScene::reload_scene(p->canvas3D, false);
+        _3DScene::zoom_to_volumes(p->canvas3D);
     }
     else {
 //         schedule_background_process();
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 023a6a67d..3b9fe0bd3 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1845,7 +1845,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
     if (!wxGetApp().mainframe)
         return;
 	on_value_change("extruders_count", extruders_count);
-    wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count);
+    wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count);
 }
 
 void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key)
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 4eaffe49f..4f7f88602 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -376,12 +376,13 @@ void  PrusaObjectDataViewModelNode::set_part_action_icon() {
 Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
 bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories)
 {
-    if (m_type != "settings" || m_opt_categories == categories)
+    if (m_type != itSettings || m_opt_categories == categories)
         return false;
 
     m_opt_categories = categories;
     m_name = wxEmptyString;
-    m_icon = m_empty_icon;
+//     m_icon = m_empty_icon;
+    m_bmp = m_empty_bmp;
 
     std::map<std::string, wxBitmap>& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON;//Slic3r::GUI::get_category_icon();
 
@@ -431,18 +432,7 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name)
 	return child;
 }
 
-wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int instances_count/*, int scale*/)
-{
-	auto root = new PrusaObjectDataViewModelNode(name, instances_count);
-	m_objects.push_back(root);
-	// notify control
-	wxDataViewItem child((void*)root);
-	wxDataViewItem parent((void*)NULL);
-	ItemAdded(parent, child);
-	return child;
-}
-
-wxDataViewItem PrusaObjectDataViewModel::AddChild(	const wxDataViewItem &parent_item,
+wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item,
 													const wxString &name,
                                                     const wxBitmap& icon,
                                                     const int extruder/* = 0*/,
@@ -453,25 +443,25 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild(	const wxDataViewItem &parent_
 
     const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder);
 
-    if (create_frst_child && (root->GetChildren().Count() == 0 || 
-                             (root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == "settings")))
+    if (create_frst_child && root->m_volumes_cnt == 0)
 	{
-		const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);
-		const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0);
+		const auto bmp_solid_mesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);
+		const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, bmp_solid_mesh, extruder_str, 0);
 		root->Append(node);
 		// notify control
 		const wxDataViewItem child((void*)node);
 		ItemAdded(parent_item, child);
+
+        root->m_volumes_cnt++;
 	}
 
-    const auto volume_id =  root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == "settings" ?
-                            root->GetChildCount() - 1 : root->GetChildCount();
-
-	const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id);
+    const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, root->m_volumes_cnt);
 	root->Append(node);
 	// notify control
 	const wxDataViewItem child((void*)node);
-	ItemAdded(parent_item, child);
+    ItemAdded(parent_item, child);
+    root->m_volumes_cnt++;
+
 	return child;
 }
 
@@ -480,7 +470,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem &
     PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID();
     if (!root) return wxDataViewItem(0);
 
-    const auto node = new PrusaObjectDataViewModelNode(root);
+    const auto node = new PrusaObjectDataViewModelNode(root, itSettings);
     root->Insert(node, 0);
     // notify control
     const wxDataViewItem child((void*)node);
@@ -488,6 +478,55 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem &
     return child;
 }
 
+int get_istances_root_idx(PrusaObjectDataViewModelNode *parent_node)
+{
+    int inst_root_id = -1;
+    int stop_search_i = parent_node->GetChildCount();
+    if (stop_search_i > 2) stop_search_i = 2;
+    for (int i = 0; i < stop_search_i; ++i)
+        if (parent_node->GetNthChild(i)->m_type & itInstanceRoot) {
+            inst_root_id = i;
+            break;
+        }
+    return inst_root_id;
+}
+
+wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num)
+{
+    PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID();
+    if (!parent_node) return wxDataViewItem(0);
+
+    // Check and create/get instances root node
+    const int inst_root_id = get_istances_root_idx(parent_node);
+
+    PrusaObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? 
+                                                   new PrusaObjectDataViewModelNode(parent_node, itInstanceRoot) :
+                                                   parent_node->GetNthChild(inst_root_id);
+    const wxDataViewItem inst_root_item((void*)inst_root_node);
+
+    if (inst_root_id < 0) {
+        const unsigned insert_pos = parent_node->GetChildCount() == 0 || parent_node->GetNthChild(0)->m_type != itSettings ? 0 : 1;
+        parent_node->Insert(inst_root_node, insert_pos);
+        // notify control
+        ItemAdded(parent_item, inst_root_item);
+        num++;
+    }
+
+    // Add instance nodes
+    PrusaObjectDataViewModelNode *instance_node = nullptr;    
+    size_t counter = 0;
+    while (counter < num){
+        instance_node = new PrusaObjectDataViewModelNode(inst_root_node, itInstance);
+        inst_root_node->Append(instance_node);
+        // notify control
+        const wxDataViewItem instance_item((void*)instance_node);
+        ItemAdded(inst_root_item, instance_item);
+        ++counter;
+    }
+
+    return wxDataViewItem((void*)instance_node);
+}
+
 wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
 {
 	auto ret_item = wxDataViewItem(0);
@@ -503,21 +542,45 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
 	//       thus removing the node from it doesn't result in freeing it
 	if (node_parent){
 		auto id = node_parent->GetChildren().Index(node);
-		auto v_id = node->GetVolumeId();
+        auto idx = node->GetIdx();
 		node_parent->GetChildren().Remove(node);
 		if (id > 0){ 
 			if(id == node_parent->GetChildCount()) id--;
 			ret_item = wxDataViewItem(node_parent->GetChildren().Item(id));
 		}
 
-		//update volume_id value for remaining child-nodes
+		//update idx value for remaining child-nodes
 		auto children = node_parent->GetChildren();
-        for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++)
+        for (size_t i = 0; i < node_parent->GetChildCount() && idx>=0; i++)
 		{
-			auto volume_id = children[i]->GetVolumeId();
-			if (volume_id > v_id)
-				children[i]->SetVolumeId(volume_id-1);
+            auto cur_idx = children[i]->GetIdx();
+			if (cur_idx > idx)
+				children[i]->SetIdx(cur_idx-1);
 		}
+
+        // if there is last instance item, delete both of it and instance root item
+        if (node_parent->GetChildCount() == 1 && node_parent->GetNthChild(0)->m_type == itInstance)
+        {
+            delete node;
+            ItemDeleted(parent, item);
+
+            PrusaObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0);
+            node_parent->GetChildren().Remove(last_instance_node);
+            delete last_instance_node;
+            ItemDeleted(parent, wxDataViewItem(last_instance_node));
+
+            PrusaObjectDataViewModelNode *obj_node = node_parent->GetParent();
+            obj_node->GetChildren().Remove(node_parent);
+            delete node_parent;
+            ret_item = wxDataViewItem(obj_node);
+            ItemDeleted(ret_item, wxDataViewItem(node_parent));
+
+#ifndef __WXGTK__
+            if (obj_node->GetChildCount() == 0)
+                obj_node->m_container = false;
+#endif //__WXGTK__
+            return ret_item;
+        }
 	}
 	else
 	{
@@ -547,6 +610,54 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
 	return ret_item;
 }
 
+wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num)
+{
+    auto ret_item = wxDataViewItem(0);
+    PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID();
+    if (!parent_node) return ret_item;
+
+    const int inst_root_id = get_istances_root_idx(parent_node);
+    if (inst_root_id < 0) return ret_item;
+
+    wxDataViewItemArray items;
+    PrusaObjectDataViewModelNode *inst_root_node = parent_node->GetNthChild(inst_root_id);
+    const wxDataViewItem inst_root_item((void*)inst_root_node);
+
+    const int inst_cnt = inst_root_node->GetChildCount();
+    const bool delete_inst_root_item = inst_cnt - num < 2 ? true : false;
+
+    int stop = delete_inst_root_item ? 0 : inst_cnt - num;
+    for (int i = inst_cnt - 1; i >= stop;--i) {
+        PrusaObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i);
+        inst_root_node->GetChildren().Remove(last_instance_node);
+        delete last_instance_node;
+        ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node));
+    }
+
+//     for (int i = delete_inst_root_item ? 0 : inst_cnt - num; i < inst_cnt; ++i)
+//         items.Add(wxDataViewItem(inst_root_node->GetNthChild(i)));
+// 
+//     if (delete_inst_root_item)
+//         inst_root_node->GetChildren().RemoveAt(0, inst_cnt);
+//     else {
+//         ret_item = wxDataViewItem(inst_root_node->GetNthChild(inst_cnt - num - 1));
+//         inst_root_node->GetChildren().RemoveAt(inst_cnt - num, num);
+//     }
+
+//     ItemsDeleted(inst_root_item, items);
+    if (delete_inst_root_item) {
+        ret_item = parent_item;
+        parent_node->GetChildren().Remove(inst_root_node);
+        ItemDeleted(parent_item, inst_root_item);
+#ifndef __WXGTK__
+        if (parent_node->GetChildCount() == 0)
+            parent_node->m_container = false;
+#endif //__WXGTK__
+    }
+
+    return ret_item;
+}
+
 void PrusaObjectDataViewModel::DeleteAll()
 {
 	while (!m_objects.empty())
@@ -606,7 +717,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu
 
     auto parent = m_objects[obj_idx];
     if (parent->GetChildCount() == 0 ||
-        (parent->GetChildCount() == 1 && parent->GetNthChild(0)->m_volume_id == -2)) {
+        (parent->GetChildCount() == 1 && parent->GetNthChild(0)->GetType() & itSettings )) {
         if (volume_idx == 0)
             return GetItemById(obj_idx);
 
@@ -615,7 +726,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu
     }
 
     for (size_t i = 0; i < parent->GetChildCount(); i++)
-        if (parent->GetNthChild(i)->m_volume_id == volume_idx)
+        if (parent->GetNthChild(i)->m_idx == volume_idx && parent->GetNthChild(0)->GetType() & itVolume)
             return wxDataViewItem(parent->GetNthChild(i));
 
     return wxDataViewItem(0);
@@ -633,31 +744,49 @@ int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item)
 	return it - m_objects.begin();
 }
 
-int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item)
+int PrusaObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const
 {
 	wxASSERT(item.IsOk());
 
 	PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
-	if (!node)      // happens if item.IsOk()==false
+	if (!node || node->m_type != type)
 		return -1;
-	return node->GetVolumeId();
+	return node->GetIdx();
 }
 
-void PrusaObjectDataViewModel::GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx)
+int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) const
+{
+    return GetIdByItemAndType(item, itVolume);
+}
+
+int PrusaObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const 
+{
+    return GetIdByItemAndType(item, itInstance);
+}
+
+void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx)
 {
     wxASSERT(item.IsOk());
-    obj_idx = vol_idx = -1;
+    type = itUndef;
 
     PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
-    if (!node) return;
-    vol_idx = node->GetVolumeId();
+    if (!node || node->GetIdx() < 0 && node->GetType() != itObject) 
+        return;
+
+    idx = node->GetIdx();
+    type = node->GetType();
 
     PrusaObjectDataViewModelNode *parent_node = node->GetParent();
     if (!parent_node) return;
+    if (type == itInstance)
+        parent_node = node->GetParent()->GetParent();
+    if (!parent_node || parent_node->m_type != itObject) { type = itUndef; return; }
 
     auto it = find(m_objects.begin(), m_objects.end(), parent_node);
     if (it != m_objects.end())
         obj_idx = it - m_objects.begin();
+    else
+        type = itUndef;
 }
 
 wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const
@@ -669,21 +798,6 @@ wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const
 	return node->m_name;
 }
 
-wxString PrusaObjectDataViewModel::GetCopy(const wxDataViewItem &item) const
-{
-	PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
-	if (!node)      // happens if item.IsOk()==false
-		return wxEmptyString;
-
-	return node->m_copy;
-}
-
-wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const
-{
-    PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
-    return node->m_icon;
-}
-
 wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const
 {
     PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
@@ -697,16 +811,13 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem
 	PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
 	switch (col)
 	{
-	case 0:{
+	case 0:
         variant << PrusaDataViewBitmapText(node->m_name, node->m_bmp);
-		break;}
-	case 1:
-		variant = node->m_copy;
 		break;
-	case 2:
+	case 1:
 		variant = node->m_extruder;
 		break;
-	case 3:
+	case 2:
 		variant << node->m_action_icon;
 		break;
 	default:
@@ -729,7 +840,7 @@ bool PrusaObjectDataViewModel::SetValue(const wxVariant &variant, const int item
 
 	return m_objects[item_idx]->SetValue(variant, col);
 }
-
+/*
 wxDataViewItem PrusaObjectDataViewModel::MoveChildUp(const wxDataViewItem &item)
 {
 	auto ret_item = wxDataViewItem(0);
@@ -777,7 +888,7 @@ wxDataViewItem PrusaObjectDataViewModel::MoveChildDown(const wxDataViewItem &ite
 		ret_item = wxDataViewItem(node_parent->GetNthChild(node_parent->GetChildCount()-1));
 	return ret_item;
 }
-
+*/
 wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_id, int new_volume_id, const wxDataViewItem &parent)
 {
     auto ret_item = wxDataViewItem(0);
@@ -788,14 +899,14 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i
     if (!node_parent)      // happens if item.IsOk()==false
         return ret_item;
 
-    const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0;
+    const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0;
 
     PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift);
     node_parent->GetChildren().Remove(deleted_node);
     ItemDeleted(parent, wxDataViewItem(deleted_node));
     node_parent->Insert(deleted_node, new_volume_id+shift);
     ItemAdded(parent, wxDataViewItem(deleted_node));
-    const auto settings_item = HasSettings(wxDataViewItem(deleted_node));
+    const auto settings_item = GetSettingsItem(wxDataViewItem(deleted_node));
     if (settings_item)
         ItemAdded(wxDataViewItem(deleted_node), settings_item);
 
@@ -804,7 +915,7 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i
     int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id;
     int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id;
     for (int id = id_frst; id <= id_last; ++id)
-        children[id+shift]->SetVolumeId(id);
+        children[id+shift]->SetIdx(id);
 
     return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift));
 }
@@ -827,12 +938,32 @@ wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) c
 	PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
 
 	// objects nodes has no parent too
-	if (find(m_objects.begin(), m_objects.end(),node) != m_objects.end())
+    if (node->m_type == itObject)
 		return wxDataViewItem(0);
 
 	return wxDataViewItem((void*)node->GetParent());
 }
 
+wxDataViewItem PrusaObjectDataViewModel::GetTopParent(const wxDataViewItem &item) const
+{
+	// the invisible root node has no parent
+	if (!item.IsOk())
+		return wxDataViewItem(0);
+
+	PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
+    if (node->m_type == itObject)
+        return item;
+
+    PrusaObjectDataViewModelNode *parent_node = node->GetParent();
+    while (parent_node->m_type != itObject)
+    {
+        node = parent_node;
+        parent_node = node->GetParent();
+    }
+
+    return wxDataViewItem((void*)parent_node);
+}
+
 bool PrusaObjectDataViewModel::IsContainer(const wxDataViewItem &item) const
 {
 	// the invisible root node can have children
@@ -868,7 +999,15 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent,
 	return count;
 }
 
-wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const
+ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const 
+{
+    if (!item.IsOk())
+        return itUndef;
+    PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
+    return node->m_type;
+}
+
+wxDataViewItem PrusaObjectDataViewModel::GetSettingsItem(const wxDataViewItem &item) const
 {
     if (!item.IsOk())
         return wxDataViewItem(0);
@@ -877,9 +1016,8 @@ wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item)
     if (node->GetChildCount() == 0)
         return wxDataViewItem(0);
 
-    auto& children = node->GetChildren();
-    if (children[0]->m_type == "settings")
-        return wxDataViewItem((void*)children[0]);;
+    if (node->GetNthChild(0)->m_type == itSettings)
+        return wxDataViewItem((void*)node->GetNthChild(0));
 
     return wxDataViewItem(0);
 }
@@ -889,7 +1027,7 @@ bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const
     if (!item.IsOk())
         return false;
     PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
-    return node->m_type == "settings";
+    return node->m_type == itSettings;
 }
 
 
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index 07f56e643..f39c38ab5 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -169,7 +169,7 @@ public:
 
     void SetText(const wxString &text)      { m_text = text; }
     wxString GetText() const                { return m_text; }
-    void SetBitmap(const wxIcon &icon)      { m_bmp = icon; }
+    void SetBitmap(const wxBitmap &bmp)      { m_bmp = bmp; }
     const wxBitmap &GetBitmap() const       { return m_bmp; }
 
     bool IsSameAs(const PrusaDataViewBitmapText& other) const {
@@ -197,6 +197,15 @@ DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText)
 // PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
 // ----------------------------------------------------------------------------
 
+enum ItemType{
+    itUndef = 0,
+    itObject = 1,
+    itVolume = 2,
+    itInstanceRoot = 4,
+    itInstance = 8,
+    itSettings = 16
+};
+
 class PrusaObjectDataViewModelNode;
 WX_DEFINE_ARRAY_PTR(PrusaObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
 
@@ -204,16 +213,14 @@ class PrusaObjectDataViewModelNode
 {
 	PrusaObjectDataViewModelNode*	m_parent;
 	MyObjectTreeModelNodePtrArray   m_children;
-    wxIcon                          m_empty_icon;
     wxBitmap                        m_empty_bmp;
+    size_t                          m_volumes_cnt = 0;
     std::vector< std::string >      m_opt_categories;
 public:
-	PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) {
+	PrusaObjectDataViewModelNode(const wxString &name) {
 		m_parent	= NULL;
 		m_name		= name;
-		m_copy		= wxString::Format("%d", instances_count);
-		m_type		= "object";
-		m_volume_id	= -1;
+		m_type		= itObject;
 #ifdef __WXGTK__
         // it's necessary on GTK because of control have to know if this item will be container
         // in another case you couldn't to add subitem for this item
@@ -227,13 +234,12 @@ public:
 									const wxString& sub_obj_name, 
 									const wxBitmap& bmp, 
                                     const wxString& extruder, 
-									const int volume_id=-1) {
+                                    const int idx = -1 ) {
 		m_parent	= parent;
 		m_name		= sub_obj_name;
-		m_copy		= wxEmptyString;
 		m_bmp		= bmp;
-		m_type		= "volume";
-		m_volume_id = volume_id;
+		m_type		= itVolume;
+        m_idx       = idx;
         m_extruder = extruder;
 #ifdef __WXGTK__
         // it's necessary on GTK because of control have to know if this item will be container
@@ -244,12 +250,22 @@ public:
 		set_part_action_icon();
     }
 
-    PrusaObjectDataViewModelNode(   PrusaObjectDataViewModelNode* parent) :
+    PrusaObjectDataViewModelNode(   PrusaObjectDataViewModelNode* parent, const ItemType type) :
                                     m_parent(parent),
-                                    m_name("Settings to modified"),
-                                    m_copy(wxEmptyString),
-                                    m_type("settings"),
-                                    m_extruder(wxEmptyString) {}
+                                    m_type(type),
+                                    m_extruder(wxEmptyString)
+	{
+        if (type == itSettings) {
+            m_name = "Settings to modified";
+        }
+        else if (type == itInstanceRoot) {
+            m_name = "Instances";            
+        }
+        else if (type == itInstance) {
+            m_idx = parent->GetChildCount();
+            m_name = wxString::Format("Instance_%d", m_idx+1);
+        }
+	}
 
 	~PrusaObjectDataViewModelNode()
 	{
@@ -263,11 +279,9 @@ public:
 	}
 	
 	wxString				m_name;
-	wxIcon&					m_icon = m_empty_icon;
     wxBitmap&               m_bmp = m_empty_bmp;
-	wxString				m_copy;
-	std::string				m_type;
-	int						m_volume_id = -2;
+    ItemType				m_type;
+    int                     m_idx = -1;
 	bool					m_container = false;
 	wxString				m_extruder = "default";
 	wxBitmap				m_action_icon;
@@ -331,12 +345,9 @@ public:
 			m_name = data.GetText();
 			return true;}
 		case 1:
-			m_copy = variant.GetString();
-			return true;
-		case 2:
 			m_extruder = variant.GetString();
 			return true;
-		case 3:
+		case 2:
 			m_action_icon << variant;
 			return true;
 		default:
@@ -344,28 +355,25 @@ public:
 		}
 		return false;
 	}
-	void SetIcon(const wxIcon &icon)
-	{
-		m_icon = icon;
-	}
 
 	void SetBitmap(const wxBitmap &icon)
 	{
 		m_bmp = icon;
 	}
-	
-	void SetType(const std::string& type){
-		m_type = type;
-	}	
-	const std::string& GetType(){
-		return m_type;
+
+    ItemType GetType() const {
+        return m_type;
+    }
+
+	void SetIdx(const int& idx) {
+		m_idx = idx;
+        // update name if this node is instance
+        if (m_type == itInstance)
+            m_name = wxString::Format("Instance_%d", m_idx + 1);
 	}
 
-	void SetVolumeId(const int& volume_id){
-		m_volume_id = volume_id;
-	}
-	const int& GetVolumeId(){
-		return m_volume_id;
+	int GetIdx() const {
+		return m_idx;
 	}
 
 	// use this function only for childrens
@@ -373,9 +381,10 @@ public:
 	{
 		// ! Don't overwrite other values because of equality of this values for all children --
 		m_name = from_node.m_name;
-		m_icon = from_node.m_icon;
-		m_volume_id = from_node.m_volume_id;
-		m_extruder = from_node.m_extruder;
+        m_bmp = from_node.m_bmp;
+        m_idx = from_node.m_idx;
+        m_extruder = from_node.m_extruder;
+        m_type = from_node.m_type;
 	}
 
 	bool SwapChildrens(int frst_id, int scnd_id) {
@@ -387,8 +396,8 @@ public:
 		PrusaObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
 		PrusaObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
 
-		new_scnd.m_volume_id = m_children.Item(scnd_id)->m_volume_id;
-		new_frst.m_volume_id = m_children.Item(frst_id)->m_volume_id;
+        new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
+        new_frst.m_idx = m_children.Item(frst_id)->m_idx;
 
 		m_children.Item(frst_id)->AssignAllVal(new_frst);
 		m_children.Item(scnd_id)->AssignAllVal(new_scnd);
@@ -399,6 +408,8 @@ public:
 	void set_object_action_icon();
 	void set_part_action_icon();
     bool update_settings_digest(const std::vector<std::string>& categories);
+private:
+    friend class PrusaObjectDataViewModel;
 };
 
 // ----------------------------------------------------------------------------
@@ -413,28 +424,29 @@ public:
     ~PrusaObjectDataViewModel();
 
 	wxDataViewItem Add(const wxString &name);
-	wxDataViewItem Add(const wxString &name, const int instances_count);
-	wxDataViewItem AddChild(const wxDataViewItem &parent_item, 
+	wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, 
 							const wxString &name, 
                             const wxBitmap& icon,
                             const int extruder = 0,
                             const bool create_frst_child = true);
 	wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
+    wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
 	wxDataViewItem Delete(const wxDataViewItem &item);
+	wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
 	void DeleteAll();
     void DeleteChildren(wxDataViewItem& parent);
 	wxDataViewItem GetItemById(int obj_idx);
 	wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
 	int GetIdByItem(const wxDataViewItem& item);
-	int GetVolumeIdByItem(const wxDataViewItem& item);
-    void GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx);
+    int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
+    int GetVolumeIdByItem(const wxDataViewItem& item) const;
+    int GetInstanceIdByItem(const wxDataViewItem& item) const;
+    void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
     bool IsEmpty() { return m_objects.empty(); }
 
 	// helper method for wxLog
 
 	wxString GetName(const wxDataViewItem &item) const;
-	wxString GetCopy(const wxDataViewItem &item) const;
-	wxIcon&  GetIcon(const wxDataViewItem &item) const;
     wxBitmap& GetBitmap(const wxDataViewItem &item) const;
 
 	// helper methods to change the model
@@ -448,8 +460,8 @@ public:
 		const wxDataViewItem &item, unsigned int col) override;
 	bool SetValue(const wxVariant &variant, const int item_idx, unsigned int col);
 
-	wxDataViewItem MoveChildUp(const wxDataViewItem &item);
-	wxDataViewItem MoveChildDown(const wxDataViewItem &item);
+// 	wxDataViewItem MoveChildUp(const wxDataViewItem &item);
+// 	wxDataViewItem MoveChildDown(const wxDataViewItem &item);
     // For parent move child from cur_volume_id place to new_volume_id 
     // Remaining items will moved up/down accordingly
     wxDataViewItem ReorganizeChildren(int cur_volume_id, 
@@ -459,6 +471,8 @@ public:
 	virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
 
 	virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
+    // get object item
+    wxDataViewItem GetTopParent(const wxDataViewItem &item) const;
 	virtual bool IsContainer(const wxDataViewItem &item) const override;
 	virtual unsigned int GetChildren(const wxDataViewItem &parent,
 		wxDataViewItemArray &array) const override;
@@ -467,7 +481,8 @@ public:
 	// In our case it is an item with all columns 
 	virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override {	return true; }
 
-    wxDataViewItem    HasSettings(const wxDataViewItem &item) const;
+    ItemType GetItemType(const wxDataViewItem &item) const ;
+    wxDataViewItem    GetSettingsItem(const wxDataViewItem &item) const;
     bool    IsSettingsItem(const wxDataViewItem &item) const;
     void    UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories);
 };