diff --git a/src/libslic3r/CutUtils.cpp b/src/libslic3r/CutUtils.cpp index 7979dc4095..b69c4cf4ee 100644 --- a/src/libslic3r/CutUtils.cpp +++ b/src/libslic3r/CutUtils.cpp @@ -14,9 +14,9 @@ namespace Slic3r { using namespace Geometry; -// Saved painting data for remapping after mesh cutting. +// Saved painting data for remapping after mesh change. struct SavedPainting { - indexed_triangle_set its; // Original mesh transformed to cut space + indexed_triangle_set its; // Original mesh TriangleSelector::TriangleSplittingData supported; TriangleSelector::TriangleSplittingData seam; TriangleSelector::TriangleSplittingData mmu; @@ -24,21 +24,24 @@ struct SavedPainting { }; // Remap painting data from saved source to a cut result mesh, and set on a volume. -static void remap_and_set_painting(ModelVolume* vol, const indexed_triangle_set& cut_its, - const SavedPainting& saved) +static void remap_and_set_painting(ModelVolume* vol, const SavedPainting* saved) { + if (!saved) { + return; + } + auto remap_one = [&](const TriangleSelector::TriangleSplittingData& src_data, FacetsAnnotation& target_facets) { if (src_data.bitstream.empty()) return; - auto result = TriangleSelector::remap_painting(saved.its, src_data, cut_its); + auto result = TriangleSelector::remap_painting(saved->its, src_data, vol->mesh().its); if (!result.bitstream.empty()) target_facets.set_data(result); }; - remap_one(saved.supported, vol->supported_facets); - remap_one(saved.seam, vol->seam_facets); - remap_one(saved.mmu, vol->mmu_segmentation_facets); - remap_one(saved.fuzzy, vol->fuzzy_skin_facets); + remap_one(saved->supported, vol->supported_facets); + remap_one(saved->seam, vol->seam_facets); + remap_one(saved->mmu, vol->mmu_segmentation_facets); + remap_one(saved->fuzzy, vol->fuzzy_skin_facets); } static void apply_tolerance(ModelVolume* vol) @@ -217,28 +220,26 @@ static void process_solid_part_cut(ModelVolume* volume, const Transform3d& insta // Add required cut parts to the objects if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) { - add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A"); - if (saved_painting && !upper_mesh.empty()) - remap_and_set_painting(upper->volumes.back(), upper_mesh.its, *saved_painting); + if (!upper_mesh.empty()) { + add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A"); + remap_and_set_painting(upper->volumes.back(), saved_painting); + } if (!lower_mesh.empty()) { add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B"); - if (saved_painting) - remap_and_set_painting(upper->volumes.back(), lower_mesh.its, *saved_painting); upper->volumes.back()->cut_info.is_from_upper = false; + remap_and_set_painting(upper->volumes.back(), saved_painting); } return; } - if (attributes.has(ModelObjectCutAttribute::KeepUpper)) { + if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper_mesh.empty()) { add_cut_volume(upper_mesh, upper, volume, cut_matrix); - if (saved_painting && !upper_mesh.empty()) - remap_and_set_painting(upper->volumes.back(), upper_mesh.its, *saved_painting); + remap_and_set_painting(upper->volumes.back(), saved_painting); } if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty()) { add_cut_volume(lower_mesh, lower, volume, cut_matrix); - if (saved_painting) - remap_and_set_painting(lower->volumes.back(), lower_mesh.its, *saved_painting); + remap_and_set_painting(lower->volumes.back(), saved_painting); } } @@ -363,21 +364,19 @@ const ModelObjectPtrs& Cut::perform_with_plane() // Save painting data before reset_extra_facets() discards it. // Only for model parts that will be cut (not modifiers/connectors). std::optional saved_painting; - if (volume->is_model_part() && !volume->mesh().empty()) { - SavedPainting sp; + if (m_attributes.has(ModelObjectCutAttribute::KeepPaint) && volume->is_any_painted() && volume->is_model_part() && !volume->mesh().empty()) { // Get mesh in cut space (same transform as process_volume_cut applies) TriangleMesh mesh(volume->mesh()); const auto volume_matrix = volume->get_matrix(); mesh.transform(inverse_cut_matrix * instance_matrix * volume_matrix, true); mesh.transform(m_cut_matrix); + SavedPainting sp; sp.its = std::move(mesh.its); sp.supported = volume->supported_facets.get_data(); sp.seam = volume->seam_facets.get_data(); sp.mmu = volume->mmu_segmentation_facets.get_data(); sp.fuzzy = volume->fuzzy_skin_facets.get_data(); - if (!sp.supported.bitstream.empty() || !sp.seam.bitstream.empty() || - !sp.mmu.bitstream.empty() || !sp.fuzzy.bitstream.empty()) - saved_painting = std::move(sp); + saved_painting = std::move(sp); } volume->reset_extra_facets(); diff --git a/src/libslic3r/CutUtils.hpp b/src/libslic3r/CutUtils.hpp index 2c477a3e2b..f39007c8a9 100644 --- a/src/libslic3r/CutUtils.hpp +++ b/src/libslic3r/CutUtils.hpp @@ -11,7 +11,7 @@ namespace Slic3r { using ModelObjectPtrs = std::vector; -enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, KeepAsParts, FlipUpper, FlipLower, PlaceOnCutUpper, PlaceOnCutLower, CreateDowels, InvalidateCutInfo }; +enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, KeepAsParts, FlipUpper, FlipLower, PlaceOnCutUpper, PlaceOnCutLower, CreateDowels, InvalidateCutInfo, KeepPaint }; using ModelObjectCutAttributes = enum_bitmask; ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 302bf47935..0de76dbef4 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1005,6 +1005,7 @@ public: bool is_seam_painted() const { return !this->seam_facets.empty(); } bool is_mm_painted() const { return !this->mmu_segmentation_facets.empty(); } bool is_fuzzy_skin_painted() const { return !this->fuzzy_skin_facets.empty(); } + bool is_any_painted() const { return is_fdm_support_painted() || is_seam_painted() || is_mm_painted() || is_fuzzy_skin_painted(); } // Orca: Implement prusa's filament shrink compensation approach // Returns 0-based indices of extruders painted by multi-material painting gizmo. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 2483f7bd1b..59c14ef205 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -3329,7 +3329,8 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) | 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(!has_connectors && !cut_with_groove && cut_mo->cut_id.id().invalid(), ModelObjectCutAttribute::InvalidateCutInfo) | + 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);