From 1299fcef4ae397a2f56e05ca81b76355cbec9628 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Sun, 10 May 2026 18:27:02 +0800 Subject: [PATCH] Remap paint after repair model --- src/slic3r/GUI/GUI_ObjectList.cpp | 7 +++++-- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 7 ++++--- src/slic3r/Utils/FixModelByCgal.cpp | 18 +++++++++++++++--- src/slic3r/Utils/FixModelByCgal.hpp | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 9da5edf6c3..93e5c94432 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -6086,10 +6086,13 @@ void ObjectList::fix_through_cgal() msg += "\n"; } - plater->clear_before_change_mesh(obj_idx); + const bool keep_painting = GUI::wxGetApp().app_config->get_bool("keep_painting"); + if (!keep_painting) { + plater->clear_before_change_mesh(obj_idx); + } const size_t volumes_before = object(obj_idx)->volumes.size(); std::string res; - if (!fix_model_with_cgal_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res)) + if (!fix_model_with_cgal_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res, keep_painting)) return false; //wxGetApp().plater()->changed_mesh(obj_idx); object(obj_idx)->ensure_on_bed(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index c2e4a19a73..da523788b8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -3321,6 +3321,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) wxBusyCursor wait; + const bool keep_painting = GUI::wxGetApp().app_config->get_bool("keep_painting"); ModelObjectCutAttributes attributes = only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) | only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) | only_if(has_connectors ? false : m_keep_as_parts, ModelObjectCutAttribute::KeepAsParts) | @@ -3330,7 +3331,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) | only_if(dowels_count > 0, ModelObjectCutAttribute::CreateDowels) | only_if(!has_connectors && !cut_with_groove && cut_mo->cut_id.id().invalid(), ModelObjectCutAttribute::InvalidateCutInfo) | - only_if(wxGetApp().app_config->get_bool("keep_painting"),ModelObjectCutAttribute::KeepPaint); + only_if(keep_painting, ModelObjectCutAttribute::KeepPaint); // update cut_id for the cut object in respect to the attributes update_object_cut_id(cut_mo->cut_id, attributes, dowels_count); @@ -3363,12 +3364,12 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) // model_name failing reason std::vector> failed_models; auto plater = wxGetApp().plater(); - auto fix_and_update_progress = [this, plater](ModelObject *model_object, const int vol_idx, const string &model_name, ProgressDialog &progress_dlg, + auto fix_and_update_progress = [this, plater, keep_painting](ModelObject *model_object, const int vol_idx, const string &model_name, ProgressDialog &progress_dlg, std::vector &succes_models, std::vector> &failed_models) { wxString msg = _L("Repairing model object"); msg += ": " + from_u8(model_name) + "\n"; std::string res; - if (!fix_model_with_cgal_gui(*model_object, vol_idx, progress_dlg, msg, res)) return false; + if (!fix_model_with_cgal_gui(*model_object, vol_idx, progress_dlg, msg, res, keep_painting)) return false; return true; }; ProgressDialog progress_dlg(_L("Repairing model object"), "", 100, find_toplevel_parent(plater), wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT, true); diff --git a/src/slic3r/Utils/FixModelByCgal.cpp b/src/slic3r/Utils/FixModelByCgal.cpp index e1f4320fec..9e2e014d93 100644 --- a/src/slic3r/Utils/FixModelByCgal.cpp +++ b/src/slic3r/Utils/FixModelByCgal.cpp @@ -13,6 +13,7 @@ #include "libslic3r/MeshBoolean.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/format.hpp" +#include "libslic3r/Thread.hpp" #include "../GUI/I18N.hpp" // Orca: This file provides utilities for repairing 3D model meshes using the CGAL library, handling mesh splitting, merging, and boolean operations. @@ -66,7 +67,7 @@ public: // Orca: Main function to repair model objects using CGAL, with progress dialog and cancellation support. // Returns false if fixing was canceled. fix_result contains error message if failed. -bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dialog, const wxString &msg_header, std::string &fix_result) +bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dialog, const wxString &msg_header, std::string &fix_result, bool keep_painting) { // Orca: Synchronization primitives for progress updates between worker thread and GUI. std::mutex mtx; @@ -94,8 +95,10 @@ bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::Pro }; // Orca: Worker thread that performs the actual model repair operations. - auto worker_thread = std::thread([&model_object, volume_idx, &ivolume, on_progress, &success, &canceled, &finished, &fix_result]() { + auto worker_thread = std::thread([&model_object, volume_idx, &ivolume, on_progress, &success, &canceled, &finished, &fix_result, keep_painting]() { try { + set_current_thread_name("cgal_fix_model"); + size_t start_volume = volume_idx == -1 ? 0 : size_t(volume_idx); size_t end_volume = volume_idx == -1 ? std::numeric_limits::max() : size_t(volume_idx); @@ -112,7 +115,7 @@ bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::Pro // Orca: Split splittable volumes into parts for individual processing. size_t parts_count = 1; if (volume->is_splittable()) { - parts_count = volume->split(1, false); // TODO: fix this + parts_count = volume->split(1, keep_painting); if (parts_count > 1) { const std::string msg = Slic3r::format(L("Split into %1% parts"), parts_count); on_progress(msg.c_str(), 10); @@ -150,6 +153,12 @@ bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::Pro ModelVolume *part_volume = model_object.volumes[part_idx]; TriangleMesh mesh = part_volume->mesh(); if (its_num_open_edges(mesh.its) != 0) { + + // Save painting for later remap + const std::optional saved_painting = keep_painting ? + part_volume->save_painting() : + std::optional{}; + std::string error; if (!MeshBoolean::cgal::repair(mesh, nullptr, &error)) throw Slic3r::RuntimeError(error.empty() ? L("Repair failed") : error.c_str()); @@ -158,6 +167,9 @@ bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::Pro part_volume->calculate_convex_hull(); part_volume->invalidate_convex_hull_2d(); part_volume->set_new_unique_id(); + + // Remap paint back + part_volume->restore_painting(saved_painting); } } diff --git a/src/slic3r/Utils/FixModelByCgal.hpp b/src/slic3r/Utils/FixModelByCgal.hpp index 3caa6d7fb9..61c8c91087 100644 --- a/src/slic3r/Utils/FixModelByCgal.hpp +++ b/src/slic3r/Utils/FixModelByCgal.hpp @@ -11,7 +11,7 @@ class ModelObject; class Print; // Return false if fixing was canceled. fix_result is empty on success. -extern bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dlg, const wxString &msg_header, std::string &fix_result); +extern bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dlg, const wxString &msg_header, std::string &fix_result, bool keep_painting); } // namespace Slic3r