From 3aadd6e0808e7aed0011f45d4c04b3230f4ef1d7 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Sat, 9 May 2026 21:48:52 +0800 Subject: [PATCH] Remap paint after mesh boolean --- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp | 32 +++++++++++++++++--- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp | 4 ++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp index bfff70d315..c7186e5d80 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp @@ -188,6 +188,19 @@ CommonGizmosDataID GLGizmoMeshBoolean::on_get_requirements() const | int(CommonGizmosDataID::ObjectClipper)); } +std::optional VolumeInfo::save_painting() const +{ + if (wxGetApp().app_config->get_bool("keep_painting")) { + std::optional saved_painting = mv->save_painting(); + if (saved_painting) { + saved_painting->mesh.transform(trafo); + } + return saved_painting; + } + + return {}; +} + void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_limit) { y = std::min(y, bottom_limit - ImGui::GetWindowHeight()); @@ -346,7 +359,9 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l std::vector temp_mesh_resuls; Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "UNION"); if (temp_mesh_resuls.size() != 0) { - generate_new_volume(true, *temp_mesh_resuls.begin()); + // For union, we want to keep paint from both meshes + std::vector> saved_paintings{m_src.save_painting(), m_tool.save_painting()}; + generate_new_volume(true, *temp_mesh_resuls.begin(), saved_paintings); wxGetApp().notification_manager()->close_plater_warning_notification(warning_text); } else { @@ -364,7 +379,9 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l std::vector temp_mesh_resuls; Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "A_NOT_B"); if (temp_mesh_resuls.size() != 0) { - generate_new_volume(m_diff_delete_input, *temp_mesh_resuls.begin()); + // For diff, we only need paint from src + std::vector> saved_paintings{m_src.save_painting()}; + generate_new_volume(m_diff_delete_input, *temp_mesh_resuls.begin(), saved_paintings); wxGetApp().notification_manager()->close_plater_warning_notification(warning_text); } else { @@ -382,7 +399,9 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l std::vector temp_mesh_resuls; Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "INTERSECTION"); if (temp_mesh_resuls.size() != 0) { - generate_new_volume(m_inter_delete_input, *temp_mesh_resuls.begin()); + // For intersection, we want to keep paint from both meshes + std::vector> saved_paintings{m_src.save_painting(), m_tool.save_painting()}; + generate_new_volume(m_inter_delete_input, *temp_mesh_resuls.begin(), saved_paintings); wxGetApp().notification_manager()->close_plater_warning_notification(warning_text); } else { @@ -420,7 +439,7 @@ void GLGizmoMeshBoolean::on_save(cereal::BinaryOutputArchive &ar) const ar(m_enable, m_operation_mode, m_selecting_state, m_diff_delete_input, m_inter_delete_input, m_src, m_tool); } -void GLGizmoMeshBoolean::generate_new_volume(bool delete_input, const TriangleMesh& mesh_result) { +void GLGizmoMeshBoolean::generate_new_volume(const bool delete_input, TriangleMesh& mesh_result, const std::vector>& saved_paintings) { wxGetApp().plater()->take_snapshot("Mesh Boolean"); @@ -429,6 +448,11 @@ void GLGizmoMeshBoolean::generate_new_volume(bool delete_input, const TriangleMe // generate new volume ModelVolume* new_volume = curr_model_object->add_volume(std::move(mesh_result)); + // Remap paintings + for (const auto& saved_painting : saved_paintings) { + new_volume->restore_painting(saved_painting, true); + } + // assign to new_volume from old_volume ModelVolume* old_volume = m_src.mv; std::string suffix; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp index c012a68dca..9c36be5cd9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp @@ -34,6 +34,8 @@ struct VolumeInfo { void serialize(Archive& ar) { ar(volume_idx, trafo); } + + std::optional save_painting() const; }; class GLGizmoMeshBoolean : public GLGizmoBase { @@ -87,7 +89,7 @@ private: VolumeInfo m_src; VolumeInfo m_tool; - void generate_new_volume(bool delete_input, const TriangleMesh& mesh_result); + void generate_new_volume(bool delete_input, TriangleMesh& mesh_result, const std::vector>& saved_paintings); }; } // namespace GUI