diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 732cacaf08..b998fbb7db 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -385,6 +385,8 @@ public: const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } + using ModelBase::set_new_unique_id; + protected: friend class Print; friend class SLAPrint; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 59148c0a36..f9ad7a39a4 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2113,31 +2113,10 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = { if (obj_idx < 0) return; - - const auto model_object = model.objects[obj_idx]; - Model model_fixed;// = new Model(); - fix_model_by_win10_sdk_gui(*model_object, this->fff_print, model_fixed); - - auto new_obj_idxs = load_model_objects(model_fixed.objects); - if (new_obj_idxs.empty()) - return; - - for(auto new_obj_idx : new_obj_idxs) { - auto o = model.objects[new_obj_idx]; - o->clear_instances(); - for (auto instance: model_object->instances) - o->add_instance(*instance); - o->invalidate_bounding_box(); - - if (o->volumes.size() == model_object->volumes.size()) { - for (int i = 0; i < o->volumes.size(); i++) { - o->volumes[i]->config.apply(model_object->volumes[i]->config); - } - } - // FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile - } - - remove(obj_idx); + fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx); + this->object_list_changed(); + this->update(); + this->schedule_background_process(); } void Plater::priv::set_current_panel(wxPanel* panel) diff --git a/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp index 4b487588a0..1daeaff269 100644 --- a/src/slic3r/Utils/FixModelByWin10.cpp +++ b/src/slic3r/Utils/FixModelByWin10.cpp @@ -216,7 +216,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED); { - on_progress(L("Exporting the source model"), 20); + on_progress(L("Exporting source model"), 20); Microsoft::WRL::ComPtr fileStream; hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel); @@ -239,7 +239,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path unsigned num_meshes = 0; hr = meshes->get_Size(&num_meshes); - on_progress(L("Repairing the model by the Netfabb service"), 40); + on_progress(L("Repairing model by the Netfabb service"), 40); Microsoft::WRL::ComPtr repairAsync; hr = model->RepairAsync(repairAsync.GetAddressOf()); @@ -248,7 +248,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path throw std::runtime_error(L("Mesh repair failed.")); repairAsync->GetResults(); - on_progress(L("Loading the repaired model"), 60); + on_progress(L("Loading repaired model"), 60); // Verify the number of meshes returned after the repair action. meshes.Reset(); @@ -316,7 +316,7 @@ public: const char* what() const throw() { return "Model repair has been canceled"; } }; -void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result) +void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx) { std::mutex mutex; std::condition_variable condition; @@ -329,6 +329,12 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr std::atomic canceled = false; std::atomic finished = false; + std::vector volumes; + if (volume_idx == -1) + volumes = model_object.volumes; + else + volumes.emplace_back(model_object.volumes[volume_idx]); + // Open a progress dialog. wxProgressDialog progress_dialog( _(L("Model fixing")), @@ -336,43 +342,64 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr 100, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); // Executing the calculation in a background thread, so that the COM context could be created with its own threading model. // (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context). - bool success = false; - auto on_progress = [&mutex, &condition, &progress](const char *msg, unsigned prcnt) { + bool success = false; + size_t ivolume = 0; + auto on_progress = [&mutex, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) { std::lock_guard lk(mutex); progress.message = msg; - progress.percent = prcnt; + progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size())); progress.updated = true; condition.notify_all(); }; - auto worker_thread = boost::thread([&model_object, &print, &result, on_progress, &success, &canceled, &finished]() { + auto worker_thread = boost::thread([&model_object, &volumes, &ivolume, on_progress, &success, &canceled, &finished]() { try { - on_progress(L("Exporting the source model"), 0); - boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - path_src += ".3mf"; - Model model; - DynamicPrintConfig config; - model.add_object(model_object); - if (! Slic3r::store_3mf(path_src.string().c_str(), &model, &config)) { + std::vector meshes_repaired; + meshes_repaired.reserve(volumes.size()); + for (; ivolume < volumes.size(); ++ ivolume) { + on_progress(L("Exporting source model"), 0); + boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + path_src += ".3mf"; + Model model; + ModelObject *model_object = model.add_object(); + model_object->add_volume(*volumes[ivolume]); + model_object->add_instance(); + if (! Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr)) { + boost::filesystem::remove(path_src); + throw std::runtime_error(L("Export of a temporary 3mf file failed")); + } + model.clear_objects(); + model.clear_materials(); + boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + path_dst += ".3mf"; + fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress, + [&canceled]() { if (canceled) throw RepairCanceledException(); }); boost::filesystem::remove(path_src); - throw std::runtime_error(L("Export of a temporary 3mf file failed")); + // PresetBundle bundle; + on_progress(L("Loading repaired model"), 80); + DynamicPrintConfig config; + bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &model); + boost::filesystem::remove(path_dst); + if (! loaded) + throw std::runtime_error(L("Import of the repaired 3mf file failed")); + if (model.objects.size() == 0) + throw std::runtime_error(L("Repaired 3MF file does not contain any object")); + if (model.objects.size() > 1) + throw std::runtime_error(L("Repaired 3MF file contains more than one object")); + if (model.objects.front()->volumes.size() == 0) + throw std::runtime_error(L("Repaired 3MF file does not contain any volume")); + if (model.objects.front()->volumes.size() > 1) + throw std::runtime_error(L("Repaired 3MF file contains more than one volume")); + meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh)); } - model.clear_objects(); - model.clear_materials(); - boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - path_dst += ".3mf"; - fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress, - [&canceled]() { if (canceled) throw RepairCanceledException(); }); - boost::filesystem::remove(path_src); - // PresetBundle bundle; - on_progress(L("Loading the repaired model"), 80); - bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &result); - result.objects[0]->name = boost::filesystem::path(model_object.name).filename().stem().string() + "_fixed"; - boost::filesystem::remove(path_dst); - if (! loaded) - throw std::runtime_error(L("Import of the repaired 3mf file failed")); + for (size_t i = 0; i < volumes.size(); ++ i) { + volumes[i]->mesh = std::move(meshes_repaired[i]); + volumes[i]->set_new_unique_id(); + } + model_object.invalidate_bounding_box(); + -- ivolume; + on_progress(L("Model repair finished"), 100); success = true; finished = true; - on_progress(L("Model repair finished"), 100); } catch (RepairCanceledException & /* ex */) { canceled = true; finished = true; diff --git a/src/slic3r/Utils/FixModelByWin10.hpp b/src/slic3r/Utils/FixModelByWin10.hpp index c148a6970d..8e47664678 100644 --- a/src/slic3r/Utils/FixModelByWin10.hpp +++ b/src/slic3r/Utils/FixModelByWin10.hpp @@ -12,12 +12,12 @@ class Print; #ifdef HAS_WIN10SDK extern bool is_windows10(); -extern void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result); +extern void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx); #else /* HAS_WIN10SDK */ inline bool is_windows10() { return false; } -inline void fix_model_by_win10_sdk_gui(const ModelObject &, const Print &, Model &) {} +inline void fix_model_by_win10_sdk_gui(ModelObject &, int) {} #endif /* HAS_WIN10SDK */