diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index 626bdef81..fd2844783 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -188,12 +188,11 @@ sub _init_tabpanel {
     # The following event is emited by the C++ Tab implementation on object settings change.
     EVT_COMMAND($self, -1, $OBJECT_SETTINGS_CHANGED_EVENT, sub {
         my ($self, $event) = @_;
-        my $obj_idx = $event->GetInt;
 
-        #my $line = $event->GetString;
-        #my ($parts_changed, $part_settings_changed) = split('',$line);
+        my $line = $event->GetString;
+        my ($obj_idx, $parts_changed, $part_settings_changed) = split('',$line);
 
-        #$self->{plater}->changed_object_settings($obj_idx, $parts_changed, $part_settings_changed);
+        $self->{plater}->changed_object_settings($obj_idx, $parts_changed, $part_settings_changed);
     });
         
 
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index bc149a828..1d2168fe8 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -837,7 +837,7 @@ sub load_model_objects {
         my $model_object = $self->{model}->objects->[$obj_idx];
 
         # Add object to list on c++ side
-        Slic3r::GUI::add_object_to_list($object->name, $model_object->instances_count, ($model_object->instances->[0]->scaling_factor * 100));
+        Slic3r::GUI::add_object_to_list($object->name, $model_object);
     
         $self->reset_thumbnail($obj_idx);
     }
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index dec2c7d7c..46e1a96d6 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -59,6 +59,7 @@
 
 #include "../Utils/PresetUpdater.hpp"
 #include "../Config/Snapshot.hpp"
+#include "Model.hpp"
 
 
 namespace Slic3r { namespace GUI {
@@ -149,6 +150,7 @@ int			m_event_object_settings_changed = 0;
 bool		g_prevent_list_events = false;		// We use this flag to avoid circular event handling Select() 
 												// happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler 
 												// calls this method again and again and again
+ModelObjectPtrs			m_objects;
 
 wxFont		g_small_font;
 wxFont		g_bold_font;
@@ -496,7 +498,7 @@ void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_languag
 	add_config_menu(menu, event_preferences_changed, event_language_change);
 }
 
-wxArrayString* open_model(wxWindow *parent){
+void open_model(wxWindow *parent, wxArrayString& input_files){
 	t_file_wild_card vec_FILE_WILDCARDS = get_file_wild_card();
 	std::vector<std::string> file_types = { "known", "stl", "obj", "amf", "3mf", "prusa" };
 	wxString MODEL_WILDCARD;
@@ -509,12 +511,11 @@ wxArrayString* open_model(wxWindow *parent){
 		MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
 	if (dialog->ShowModal() != wxID_OK) {
 		dialog->Destroy();
-		return nullptr;
+		return ;
 	}
-	wxArrayString input_files;
+	
 	dialog->GetPaths(input_files);
 	dialog->Destroy();
-	return &input_files;
 }
 
 // This is called when closing the application, when loading a config file or when starting the config wizard
@@ -810,6 +811,24 @@ unsigned get_colour_approx_luma(const wxColour &colour)
 		b * b * .068
 	));
 }
+wxDataViewCtrl*		get_objects_ctrl() {
+	return m_objects_ctrl;
+}
+MyObjectTreeModel*	get_objects_model() {
+	return m_objects_model;
+}
+
+ModelObjectPtrs& get_objects() {
+	return m_objects;
+}
+
+const int& get_event_object_settings_changed() {
+	return m_event_object_settings_changed;
+}
+
+wxFrame* get_main_frame() {
+	return g_wxMainFrame;
+}
 
 void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value)
 {
@@ -996,27 +1015,14 @@ wxBoxSizer* content_edit_object_buttons(wxWindow* win)
 	auto btn_move_down = new wxButton(win, wxID_ANY, "", wxDefaultPosition, wxDefaultSize/*wxSize(30, -1)*/, wxBU_LEFT);
 
 	//*** button's functions
-	btn_load_part->Bind(wxEVT_BUTTON, [](wxEvent&)
+	btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&)
 	{
-		auto item = m_objects_ctrl->GetSelection();
-		if (!item) return;
-		if (m_objects_model->GetParent(item) != wxDataViewItem(0))
-			item = m_objects_model->GetParent(item);
-		if (!item) return;
-		wxString name = "Part";
-		m_objects_ctrl->Select(m_objects_model->AddChild(item, name));
+		on_btn_load(win);
 	});
 
 	btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&)
 	{
 		on_btn_load(win, true);
-// 		auto item = m_objects_ctrl->GetSelection();
-// 		if (!item) return;
-// 		if (m_objects_model->GetParent(item) != wxDataViewItem(0))
-// 			item = m_objects_model->GetParent(item);
-// 		if (!item) return;
-// 		wxString name = "Part";
-// 		m_objects_ctrl->Select(m_objects_model->AddChild(item, name));
 	});
 
 	btn_delete->Bind(wxEVT_BUTTON, [](wxEvent&)
@@ -1171,10 +1177,12 @@ wxBoxSizer* content_settings(wxWindow *win)
 	return sizer;
 }
 
-void add_object_to_list(const std::string &name, int instances_count, int scale)
+void add_object_to_list(const std::string &name, ModelObject* model_object)
 {
 	wxString item = name;
-	m_objects_ctrl->Select(m_objects_model->Add(item, instances_count, scale));
+	int scale = model_object->instances[0]->scaling_factor * 100;
+	m_objects_ctrl->Select(m_objects_model->Add(item, model_object->instances.size(), scale));
+	m_objects.push_back(model_object);
 }
 
 void delete_object_from_list()
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 22b41fb20..5c5a1a6a9 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -25,6 +25,8 @@ class wxButton;
 class wxFileDialog;
 class wxStaticBitmap;
 class wxFont;
+class wxDataViewCtrl;
+class MyObjectTreeModel;
 
 namespace Slic3r { 
 
@@ -34,6 +36,7 @@ class AppConfig;
 class PresetUpdater;
 class DynamicPrintConfig;
 class TabIface;
+class ModelObject;
 
 #define _(s)    Slic3r::translate((s))
 inline wxString translate(const char *s)    	 { return wxGetTranslation(wxString(s, wxConvUTF8)); }
@@ -67,6 +70,7 @@ enum ogGroup{
 
 class Tab;
 class ConfigOptionsGroup;
+typedef std::vector<ModelObject*> ModelObjectPtrs;
 // Map from an file_type name to full file wildcard name.
 typedef std::map<std::string, std::string> t_file_wild_card;
 inline t_file_wild_card& get_file_wild_card() {
@@ -124,7 +128,13 @@ void set_label_clr_sys(const wxColour& clr);
 const wxFont& small_font();
 const wxFont& bold_font();
 
-wxArrayString* open_model(wxWindow *parent);
+void open_model(wxWindow *parent, wxArrayString& input_files);
+
+wxDataViewCtrl*		get_objects_ctrl ();
+MyObjectTreeModel*	get_objects_model();
+ModelObjectPtrs&	get_objects();
+const int&			get_event_object_settings_changed();
+wxFrame*			get_main_frame();
 
 extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
 
@@ -191,7 +201,7 @@ wxString	from_u8(const std::string &str);
 
 // Add object to the list
 //void add_object(const std::string &name);
-void add_object_to_list(const std::string &name, int instances_count=1, int scale=100);
+void add_object_to_list(const std::string &name, ModelObject* model_object);
 // Delete object from the list
 void delete_object_from_list();
 // Delete all objects from the list
diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
index a5abf2af6..57d46c977 100644
--- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
+++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
@@ -1,42 +1,96 @@
 #include "GUI.hpp"
 #include "GUI_ObjectParts.hpp"
+#include "Model.hpp"
+#include "wxExtensions.hpp"
 
 #include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <boost/filesystem.hpp>
 
 namespace Slic3r
 {
 namespace GUI
 {
-void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/)
-{
-	auto input_files = open_model(parent);
-// 	for(auto input_file : input_files) {
-// 		my $model = eval{ Slic3r::Model->read_from_file($input_file) };
-// 		if ($@) {
-// 			Slic3r::GUI::show_error($self, $@);
-// 			next;
-// 		}
+bool m_parts_changed = false;
+bool m_part_settings_changed = false;
 
-// 		foreach my $object(@{$model->objects}) {
-// 			foreach my $volume(@{$object->volumes}) {
-// 				my $new_volume = $self->{model_object}->add_volume($volume);
-// 				$new_volume->set_modifier($is_modifier);
-// 				$new_volume->set_name(basename($input_file));
-// 
-// 				# apply the same translation we applied to the object
-// 				$new_volume->mesh->translate(@{$self->{model_object}->origin_translation});
-// 
-// 				# set a default extruder value, since user can't add it manually
-// 				$new_volume->config->set_ifndef('extruder', 0);
-// 
-// 				$self->{parts_changed} = 1;
-// 			}
-// 		}
-// 	}
+bool is_parts_changed(){return m_parts_changed;}
+bool is_part_settings_changed(){ return m_part_settings_changed; }
+
+void load_part(wxWindow* parent, ModelObject* model_object, wxArrayString& part_names, bool is_modifier)
+{
+	wxArrayString input_files;
+	open_model(parent, input_files);
+	for (int i = 0; i < input_files.size(); ++i) {
+		std::string input_file = input_files.Item(i).ToStdString();
+
+		Model model;
+		try {
+			model = Model::read_from_file(input_file);
+		}
+		catch (std::exception &e) {
+			auto msg = _(L("Error! ")) + input_file + " : " + e.what() + ".";
+			show_error(parent, msg);
+			exit(1);
+		}
+
+		for ( auto object : model.objects) {
+			for (auto volume : object->volumes) {
+				auto new_volume = model_object->add_volume(*volume);
+				new_volume->modifier = is_modifier;
+				boost::filesystem::path(input_file).filename().string();
+				new_volume->name = boost::filesystem::path(input_file).filename().string();
+
+				part_names.Add(new_volume->name);
+
+				// apply the same translation we applied to the object
+				new_volume->mesh.translate( model_object->origin_translation.x,
+											model_object->origin_translation.y, 
+											model_object->origin_translation.y );
+
+				// set a default extruder value, since user can't add it manually
+				new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
+
+				m_parts_changed = true;
+			}
+		}
+	}
 
 	parts_changed();
 }
 
+void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/)
+{
+	auto objects_ctrl = get_objects_ctrl();
+	auto item = objects_ctrl->GetSelection();
+	if (!item)
+		return;
+	int obj_idx = -1;
+	auto objects_model = get_objects_model();
+	if (objects_model->GetParent(item) == wxDataViewItem(0))
+		obj_idx = objects_model->GetIdByItem(item);
+	else
+		return;
+
+	if (obj_idx < 0) return;
+	wxArrayString part_names;
+	ModelObjectPtrs& objects = get_objects();
+	load_part(parent, objects[obj_idx], part_names, is_modifier);
+
+	auto event = get_event_object_settings_changed();
+	if (event > 0) {
+		wxCommandEvent e(event);
+		auto event_str = wxString::Format("%d %d %d", obj_idx,
+			is_parts_changed() ? 1 : 0,
+			is_part_settings_changed() ? 1 : 0);
+		e.SetString(event_str);
+		get_main_frame()->ProcessWindowEvent(e);
+	}
+
+	for (int i = 0; i < part_names.size(); ++i)
+		objects_ctrl->Select(objects_model->AddChild(item, part_names.Item(i)));
+}
+
 void parts_changed(){ ; }
 
 } //namespace GUI
diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
index ffbda35bf..9ee982b96 100644
--- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
+++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
@@ -5,6 +5,11 @@ namespace Slic3r
 {
 namespace GUI
 {
+bool is_parts_changed();
+bool is_part_settings_changed();
+
+void load_part(	wxWindow* parent, ModelObject* model_object, 
+				wxArrayString& part_names, bool is_modifier); 
 void on_btn_load(wxWindow* parent, bool is_modifier = false);
 void parts_changed();		
 } //namespace GUI
diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp
index ba800f38a..2c5e7fccd 100644
--- a/xs/xsp/GUI.xsp
+++ b/xs/xsp/GUI.xsp
@@ -122,8 +122,10 @@ void set_show_manifold_warning_icon(bool show)
 void update_mode()
     %code%{ Slic3r::GUI::update_mode(); %};
 
-void add_object_to_list(const char *name, int instances_count, int scale)
-    %code%{ Slic3r::GUI::add_object_to_list(name, instances_count, scale); %};
+void add_object_to_list(const char *name, SV *object_model)
+    %code%{ Slic3r::GUI::add_object_to_list(
+                    name, 
+                    (ModelObject *)wxPli_sv_2_object(aTHX_ object_model, "Slic3r::Model::Object") ); %};
 
 void delete_object_from_list()
     %code%{ Slic3r::GUI::delete_object_from_list(); %};