From 0c7c9d5754ca809bca7a7f87e3f296d1f11a4a1c Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Wed, 5 Dec 2018 15:22:03 +0100
Subject: [PATCH] Plater: single object STL export and reloading Based on
 Plater.pm`export_object_stl() and reload_from_disk()

---
 lib/Slic3r/GUI/Plater.pm  |  4 +--
 src/slic3r/GUI/Plater.cpp | 56 ++++++++++++++++++++++++++++++++-------
 src/slic3r/GUI/Plater.hpp |  2 +-
 3 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index d2a7a23b1..db360c811 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -1876,7 +1876,7 @@ sub export_stl {
     $self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
 }
 
-# XXX: not done
+# XXX: VK: done
 sub reload_from_disk {
     my ($self) = @_;
     
@@ -1908,7 +1908,7 @@ sub reload_from_disk {
     $self->remove($obj_idx);
 }
 
-# XXX: VK: done
+# XXX: VK: integrated into Plater::export_stl()
 sub export_object_stl {
     my ($self) = @_;
     my ($obj_idx, $object) = $self->selected_object;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 6d2af3b8d..2a99d2c5c 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -911,7 +911,7 @@ struct Plater::priv
     wxMenuItem* item_sla_autorot = nullptr;
 
     // Data
-    Slic3r::DynamicPrintConfig *config;
+    Slic3r::DynamicPrintConfig *config;        // FIXME: leak?
     Slic3r::Print               fff_print;
 	Slic3r::SLAPrint            sla_print;
     Slic3r::Model               model;
@@ -1007,7 +1007,6 @@ struct Plater::priv
     unsigned int update_background_process();
     void async_apply_config();
     void reload_from_disk();
-    void export_object_stl();
     void fix_through_netfabb(const int obj_idx);
 
 #if ENABLE_REMOVE_TABS_FROM_PLATER
@@ -2088,12 +2087,33 @@ void Plater::priv::update_sla_scene()
 
 void Plater::priv::reload_from_disk()
 {
-    // TODO
-}
+    const auto &selection = get_selection();
+    const auto obj_orig_idx = selection.get_object_idx();
+    if (selection.is_wipe_tower() || obj_orig_idx == -1) { return; }
 
-void Plater::priv::export_object_stl()
-{
-    // TODO
+    auto *object_orig = model.objects[obj_orig_idx];
+    std::vector<fs::path> input_paths(1, object_orig->input_file);
+
+    const auto new_idxs = load_files(input_paths, true, false);
+
+    for (const auto idx : new_idxs) {
+        ModelObject *object = model.objects[idx];
+
+        object->clear_instances();
+        for (const ModelInstance *instance : object_orig->instances) {
+            object->add_instance(*instance);
+        }
+
+        if (object->volumes.size() == object_orig->volumes.size()) {
+            for (size_t i = 0; i < object->volumes.size(); i++) {
+                object->volumes[i]->config.apply(object_orig->volumes[i]->config);
+            }
+        }
+
+        // XXX: Restore more: layer_height_ranges, layer_height_profile, layer_height_profile_valid (?)
+    }
+
+    remove(obj_orig_idx);
 }
 
 void Plater::priv::fix_through_netfabb(const int obj_idx)
@@ -2477,6 +2497,12 @@ bool Plater::priv::init_object_menu()
 
     wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png");
 
+    append_menu_item(&object_menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
+        [this](wxCommandEvent&) { reload_from_disk(); });
+
+    append_menu_item(&object_menu, wxID_ANY, _(L("Export object as STL…")), _(L("Export this single object as STL file")),
+        [this](wxCommandEvent&) { q->export_stl(true); });
+
     // Add the automatic rotation sub-menu
     item_sla_autorot = append_menu_item(&object_menu, wxID_ANY, _(L("Optimize orientation")), _(L("Optimize the rotation of the object for better print results.")),
                                             [this](wxCommandEvent&) { sla_optimize_rotation(); });
@@ -2845,7 +2871,7 @@ void Plater::export_gcode(fs::path output_path)
     }
 }
 
-void Plater::export_stl()
+void Plater::export_stl(bool selection_only)
 {
     if (p->model.objects.empty()) { return; }
 
@@ -2855,7 +2881,19 @@ void Plater::export_stl()
     // Store a binary STL
     wxString path = dialog->GetPath();
     auto path_cstr = path.c_str();
-    auto mesh = p->model.mesh();
+
+    TriangleMesh mesh;
+    if (selection_only) {
+        const auto &selection = p->get_selection();
+        if (selection.is_wipe_tower()) { return; }
+
+        const auto obj_idx = selection.get_object_idx();
+        if (obj_idx == -1) { return; }
+        mesh = p->model.objects[obj_idx]->mesh();
+    } else {
+        auto mesh = p->model.mesh();
+    }
+
     Slic3r::store_stl(path_cstr, &mesh, true);
     p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
 }
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 74dd790d2..242a7b39f 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -146,7 +146,7 @@ public:
 
     // Note: empty path means "use the default"
     void export_gcode(boost::filesystem::path output_path = boost::filesystem::path());
-    void export_stl();
+    void export_stl(bool selection_only = false);
     void export_amf();
     void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
     void reslice();