From 79e8e8627f403fc442d831b8a087528b7951c427 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 20 Aug 2021 11:24:48 +0200 Subject: [PATCH 1/5] Tech ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT - fixed export/import to/from 3mf file of mirrored volumes --- src/libslic3r/Format/3mf.cpp | 27 +++++++++++++++++++++++++++ src/libslic3r/Technologies.hpp | 2 ++ 2 files changed, 29 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 2a76f218f..febeacdbe 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1839,11 +1839,17 @@ namespace Slic3r { Transform3d volume_matrix_to_object = Transform3d::Identity(); bool has_transform = false; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + bool is_left_handed = false; +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT // extract the volume transformation from the volume's metadata, if present for (const Metadata& metadata : volume_data.metadata) { if (metadata.key == MATRIX_KEY) { volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value); has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10); +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + is_left_handed = Slic3r::Geometry::Transformation(volume_matrix_to_object).is_left_handed(); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT break; } } @@ -1875,6 +1881,13 @@ namespace Slic3r { stl_get_size(&stl); triangle_mesh.repair(); +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + // PrusaSlicer older than 2.4.0 saved mirrored volumes with reversed winding of the triangles + // This caused the call to TriangleMesh::repair() to reverse all the facets because the calculated volume was negative + if (is_left_handed && stl.stats.facets_reversed > 0 && stl.stats.facets_reversed == stl.stats.original_num_facets) + stl.stats.facets_reversed = 0; +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + if (m_version == 0) { // if the 3mf was not produced by PrusaSlicer and there is only one instance, // bake the transformation into the geometry to allow the reload from disk command @@ -2499,6 +2512,10 @@ namespace Slic3r { if (volume == nullptr) continue; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + bool is_left_handed = volume->is_left_handed(); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + VolumeToOffsetsMap::iterator volume_it = volumes_offsets.find(volume); assert(volume_it != volumes_offsets.end()); @@ -2513,6 +2530,15 @@ namespace Slic3r { { const Vec3i &idx = its.indices[i]; char *ptr = buf; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << TRIANGLE_TAG << + " v1=\"" << boost::spirit::int_ << + "\" v2=\"" << boost::spirit::int_ << + "\" v3=\"" << boost::spirit::int_ << "\"", + idx[is_left_handed ? 2 : 0] + volume_it->second.first_vertex_id, + idx[1] + volume_it->second.first_vertex_id, + idx[is_left_handed ? 0 : 2] + volume_it->second.first_vertex_id); +#else boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << TRIANGLE_TAG << " v1=\"" << boost::spirit::int_ << "\" v2=\"" << boost::spirit::int_ << @@ -2520,6 +2546,7 @@ namespace Slic3r { idx[0] + volume_it->second.first_vertex_id, idx[1] + volume_it->second.first_vertex_id, idx[2] + volume_it->second.first_vertex_id); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT *ptr = '\0'; output_buffer += buf; } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index f6366c18e..d337fdc2d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -47,6 +47,8 @@ #define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) // Enable drawing contours, at cut level, for sinking volumes #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) +// Enable the fix for exporting and importing to/from 3mf file of mirrored volumes +#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA0) #endif // _prusaslicer_technologies_h_ From 6be99f941dcaaf477961ca740ebeae66046d2341 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 30 Aug 2021 10:25:21 +0200 Subject: [PATCH 2/5] Escaping of backslash --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index d34d0730e..935121935 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -28,7 +28,7 @@ namespace { std::string escape_string(const std::string& str) { // The buffer needs to be bigger if escaping <,>,& - std::vector out(str.size() * 2, 0); + std::vector out(str.size() * 4, 0); char *outptr = out.data(); for (size_t i = 0; i < str.size(); ++ i) { char c = str[i]; @@ -45,6 +45,8 @@ std::string escape_string(const std::string& str) } else if (c == '\\') { // backslash character (*outptr ++) = '\\'; (*outptr ++) = '\\'; + (*outptr ++) = '\\'; + (*outptr ++) = '\\'; // Reserved characters // At Ubuntu, all these characters must NOT be escaped for desktop integration to work /* From 57f7b49223d231d7f160a13c55f6bc8d02c16b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 30 Aug 2021 10:41:01 +0200 Subject: [PATCH 3/5] Corrected undo/redo snapshot name when entering or leaving multi-material painting gizmo. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 10 ++-------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp | 3 +++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index 019ed15f4..f2c19ba5c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -19,6 +19,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Paint-on supports"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Paint-on supports"); } + private: bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index afd5854a0..ab58ba186 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -128,6 +128,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Multimaterial painting"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Multimaterial painting"); } + size_t m_first_selected_extruder_idx = 0; size_t m_second_selected_extruder_idx = 1; std::vector m_original_extruders_names; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index ac9d7adcf..9477b89c7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -47,20 +47,14 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate) plater->undo_redo_topmost_string_getter(plater->can_undo(), last_snapshot_name); if (activate && !m_internal_stack_active) { - std::string str = get_painter_type() == PainterGizmoType::FDM_SUPPORTS - ? _u8L("Entering Paint-on supports") - : _u8L("Entering Seam painting"); - if (last_snapshot_name != str) + if (std::string str = this->get_gizmo_entering_text(); last_snapshot_name != str) Plater::TakeSnapshot(plater, str); plater->enter_gizmos_stack(); m_internal_stack_active = true; } if (!activate && m_internal_stack_active) { plater->leave_gizmos_stack(); - std::string str = get_painter_type() == PainterGizmoType::SEAM - ? _u8L("Leaving Seam painting") - : _u8L("Leaving Paint-on supports"); - if (last_snapshot_name != str) + if (std::string str = this->get_gizmo_leaving_text(); last_snapshot_name != str) Plater::TakeSnapshot(plater, str); m_internal_stack_active = false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 4db17d597..c20c8140d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -173,6 +173,9 @@ protected: virtual wxString handle_snapshot_action_name(bool shift_down, Button button_down) const = 0; + virtual std::string get_gizmo_entering_text() const = 0; + virtual std::string get_gizmo_leaving_text() const = 0; + friend class ::Slic3r::GUI::GLGizmoMmuSegmentation; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index 196fe5023..7a00a9d8e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -20,6 +20,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Seam painting"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Seam painting"); } + private: bool on_init() override; From 9c1c72325305455bbf73ad9b76d4b2cc7ed900e9 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 11:46:26 +0200 Subject: [PATCH 4/5] Fixed volume name when loading a 3mf, saved with 3rd part software, as project --- src/libslic3r/Format/3mf.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index e5007a3f4..57b0d8115 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1837,6 +1837,7 @@ namespace Slic3r { } unsigned int geo_tri_count = (unsigned int)geometry.triangles.size() / 3; + unsigned int renamed_volumes_count = 0; for (const ObjectMetadata::VolumeMetadata& volume_data : volumes) { if (geo_tri_count <= volume_data.first_triangle_id || geo_tri_count <= volume_data.last_triangle_id || volume_data.last_triangle_id < volume_data.first_triangle_id) { @@ -1958,6 +1959,14 @@ namespace Slic3r { else volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions); } + + // this may happen for 3mf saved by 3rd part softwares + if (volume->name.empty()) { + volume->name = object.name; + if (renamed_volumes_count > 0) + volume->name += "_" + std::to_string(renamed_volumes_count + 1); + ++renamed_volumes_count; + } } return true; From c32f2fb7659cc0ac9923e6774bb94382f186ec39 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 12:14:45 +0200 Subject: [PATCH 5/5] New project command enabled when the plater is empty but the project state is marked as dirty --- src/slic3r/GUI/MainFrame.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 329a9a62a..900b9e59f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -620,7 +620,10 @@ void MainFrame::update_title() wxString dirty_marker = (!m_plater->model().objects.empty() && m_plater->is_project_dirty()) ? "*" : ""; if (!dirty_marker.empty() || !project.empty()) { if (!dirty_marker.empty() && project.empty()) - project = _("Untitled"); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + project = _L("Untitled"); +// project = _("Untitled"); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ title = dirty_marker + project + " - "; } } @@ -819,7 +822,7 @@ bool MainFrame::is_active_and_shown_tab(Tab* tab) bool MainFrame::can_start_new_project() const { - return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || !m_plater->model().objects.empty()); + return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || GetTitle().StartsWith('*') || !m_plater->model().objects.empty()); } bool MainFrame::can_save() const