From 0c0c37b76c96946ccd5e88762ef60465a185296b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 24 Sep 2021 09:36:14 +0200 Subject: [PATCH 01/28] Fix of [2.4.0a] version placeholder doesn't work for output filename format #7002 --- src/libslic3r/PrintBase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/PrintBase.cpp b/src/libslic3r/PrintBase.cpp index c4b6b7ccea..7de74035bc 100644 --- a/src/libslic3r/PrintBase.cpp +++ b/src/libslic3r/PrintBase.cpp @@ -60,6 +60,7 @@ std::string PrintBase::output_filename(const std::string &format, const std::str DynamicConfig cfg; if (config_override != nullptr) cfg = *config_override; + cfg.set_key_value("version", new ConfigOptionString(std::string(SLIC3R_VERSION))); PlaceholderParser::update_timestamp(cfg); this->update_object_placeholders(cfg, default_ext); if (! filename_base.empty()) { From 3872524dc481111a6bcba54e04bced927750d532 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 24 Sep 2021 10:13:26 +0200 Subject: [PATCH 02/28] Follow-up to b6d7601eadbd1f7004ac05680e10d3f9d1ea360f Fixing the FDM raft generator. --- src/libslic3r/SupportMaterial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index d1234bc1af..280936418c 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -1630,7 +1630,7 @@ static inline std::pair 1 ? slicing_params.raft_interface_top_z + support_layer_height_min + EPSILON : slicing_params.first_print_layer_height - EPSILON; if (print_z < min_print_z) { // This contact layer is below the first layer height, therefore not printable. Don't support this surface. return std::pair(nullptr, nullptr); From acd2448f1052d366d78301392b9f7bb5bd9d191f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 24 Sep 2021 10:15:46 +0200 Subject: [PATCH 03/28] Fix stl export on Linux --- src/libslic3r/TriangleMesh.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 73ac2eade5..39815bd644 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include From 60d8a7b3011e6b0dce2300427e462f8a3c1ef84f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 24 Sep 2021 10:53:11 +0200 Subject: [PATCH 04/28] MSW specific: Follow up https://github.com/prusa3d/PrusaSlicer/commit/683cb4245440fc8926e39bf4b24f42073ab43e35 - Set Selection for the content of focused controls (TextCtrls a SpinCtrls) --- src/slic3r/GUI/Tab.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6b7044b0df..c91ac47843 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1188,11 +1188,21 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category) break; } + auto set_focus = [](wxWindow* win) { + win->SetFocus(); +#ifdef WIN32 + if (wxTextCtrl* text = dynamic_cast(win)) + text->SetSelection(-1, -1); + else if (wxSpinCtrl* spin = dynamic_cast(win)) + spin->SetSelection(-1, -1); +#endif // WIN32 + }; + Field* field = get_field(opt_key); // focused selected field if (field) - field->getWindow()->SetFocus(); + set_focus(field->getWindow()); else if (category == "Single extruder MM setup") { // When we show and hide "Single extruder MM setup" page, // related options are still in the search list @@ -1200,7 +1210,7 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category) // as a "way" to show hidden page again field = get_field("single_extruder_multi_material"); if (field) - field->getWindow()->SetFocus(); + set_focus(field->getWindow()); } m_highlighter.init(get_custom_ctrl_with_blinking_ptr(opt_key)); From 6c37955d7550bdc1c09833ffcdb21936332992bc Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 24 Sep 2021 11:32:10 +0200 Subject: [PATCH 05/28] Moved a commented out test for DynamicPrintConfig serialization / deserialization into a living unit test. --- src/slic3r/Utils/UndoRedo.cpp | 40 --------------------------------- tests/libslic3r/test_config.cpp | 35 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index 6d6753ea29..a19788ab91 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -1102,43 +1102,3 @@ bool Stack::temp_snapshot_active() const { return pimpl->temp_snapshot_active(); } // namespace UndoRedo } // namespace Slic3r - - -//FIXME we should have unit tests for testing serialization of basic types as DynamicPrintConfig. -#if 0 -#include "libslic3r/Config.hpp" -#include "libslic3r/PrintConfig.hpp" -namespace Slic3r { - bool test_dynamic_print_config_serialization() { - FullPrintConfig full_print_config; - DynamicPrintConfig cfg; - cfg.apply(full_print_config, false); - - std::string serialized; - try { - std::ostringstream ss; - cereal::BinaryOutputArchive oarchive(ss); - oarchive(cfg); - serialized = ss.str(); - } catch (std::runtime_error e) { - e.what(); - } - - DynamicPrintConfig cfg2; - try { - std::stringstream ss(serialized); - cereal::BinaryInputArchive iarchive(ss); - iarchive(cfg2); - } catch (std::runtime_error e) { - e.what(); - } - - if (cfg == cfg2) { - printf("Yes!\n"); - return true; - } - printf("No!\n"); - return false; - } -} // namespace Slic3r -#endif diff --git a/tests/libslic3r/test_config.cpp b/tests/libslic3r/test_config.cpp index 97729ac8e0..2131050844 100644 --- a/tests/libslic3r/test_config.cpp +++ b/tests/libslic3r/test_config.cpp @@ -3,6 +3,11 @@ #include "libslic3r/PrintConfig.hpp" #include "libslic3r/LocalesUtils.hpp" +#include +#include +#include +#include + using namespace Slic3r; SCENARIO("Generic config validation performs as expected.", "[Config]") { @@ -202,3 +207,33 @@ SCENARIO("Config ini load/save interface", "[Config]") { } } } + +SCENARIO("DynamicPrintConfig serialization", "[Config]") { + WHEN("DynamicPrintConfig is serialized and deserialized") { + FullPrintConfig full_print_config; + DynamicPrintConfig cfg; + cfg.apply(full_print_config, false); + + std::string serialized; + try { + std::ostringstream ss; + cereal::BinaryOutputArchive oarchive(ss); + oarchive(cfg); + serialized = ss.str(); + } catch (std::runtime_error e) { + e.what(); + } + + THEN("Config object contains ini file options.") { + DynamicPrintConfig cfg2; + try { + std::stringstream ss(serialized); + cereal::BinaryInputArchive iarchive(ss); + iarchive(cfg2); + } catch (std::runtime_error e) { + e.what(); + } + REQUIRE(cfg == cfg2); + } + } +} From 7eea15fdde9ba5e9f324428f37354ba9a1793df7 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 24 Sep 2021 13:01:16 +0200 Subject: [PATCH 06/28] Set the project state to 'dirty' only if a project has a name (was saved or loaded). Do not mark the project as dirty if it is a new project which hasn't been saved yet. --- src/slic3r/GUI/ProjectDirtyStateManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/ProjectDirtyStateManager.cpp b/src/slic3r/GUI/ProjectDirtyStateManager.cpp index 3ca764e913..4ce806b2a8 100644 --- a/src/slic3r/GUI/ProjectDirtyStateManager.cpp +++ b/src/slic3r/GUI/ProjectDirtyStateManager.cpp @@ -195,8 +195,10 @@ void ProjectDirtyStateManager::update_from_undo_redo_stack(UpdateType type) void ProjectDirtyStateManager::update_from_presets() { m_state.presets = false; - for (const auto& [type, name] : wxGetApp().get_selected_presets()) { - m_state.presets |= !m_initial_presets[type].empty() && m_initial_presets[type] != name; + // check switching of the presets only for exist/loaded project, but not for new + if (!wxGetApp().plater()->get_project_filename().IsEmpty()) { + for (const auto& [type, name] : wxGetApp().get_selected_presets()) + m_state.presets |= !m_initial_presets[type].empty() && m_initial_presets[type] != name; } m_state.presets |= wxGetApp().has_unsaved_preset_changes(); wxGetApp().mainframe->update_title(); From fec5d92bc8a337492dc4ba7ca3d8e74f658d5a56 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 24 Sep 2021 14:07:46 +0200 Subject: [PATCH 07/28] Added various has_duplicate_points() checks, to be used by asserts. Removed some "extern" function modifiers, they have no meaning in C++. --- src/libslic3r/ClipperUtils.cpp | 39 ++++++++++++++++++++++ src/libslic3r/ExPolygon.cpp | 60 +++++++++++++++++++++++++++++++--- src/libslic3r/ExPolygon.hpp | 20 +++++++----- src/libslic3r/Point.cpp | 9 +++++ src/libslic3r/Point.hpp | 30 +++++++++++++++-- src/libslic3r/Polygon.cpp | 21 ++++++++++++ src/libslic3r/Polygon.hpp | 31 ++++++++++-------- 7 files changed, 183 insertions(+), 27 deletions(-) diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index a1dd638cae..e8f87a6e3d 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -126,6 +126,45 @@ ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input) return PolyTreeToExPolygons(std::move(polytree)); } +#if 0 +// Global test. +bool has_duplicate_points(const ClipperLib::PolyTree &polytree) +{ + struct Helper { + static void collect_points_recursive(const ClipperLib::PolyNode &polynode, ClipperLib::Path &out) { + // For each hole of the current expolygon: + out.insert(out.end(), polynode.Contour.begin(), polynode.Contour.end()); + for (int i = 0; i < polynode.ChildCount(); ++ i) + collect_points_recursive(*polynode.Childs[i], out); + } + }; + ClipperLib::Path pts; + for (int i = 0; i < polytree.ChildCount(); ++ i) + Helper::collect_points_recursive(*polytree.Childs[i], pts); + return has_duplicate_points(std::move(pts)); +} +#else +// Local test inside each of the contours. +bool has_duplicate_points(const ClipperLib::PolyTree &polytree) +{ + struct Helper { + static bool has_duplicate_points_recursive(const ClipperLib::PolyNode &polynode) { + if (has_duplicate_points(polynode.Contour)) + return true; + for (int i = 0; i < polynode.ChildCount(); ++ i) + if (has_duplicate_points_recursive(*polynode.Childs[i])) + return true; + return false; + } + }; + ClipperLib::Path pts; + for (int i = 0; i < polytree.ChildCount(); ++ i) + if (Helper::has_duplicate_points_recursive(*polytree.Childs[i])) + return true; + return false; +} +#endif + // Offset outside by 10um, one by one. template static ClipperLib::Paths safety_offset(PathsProvider &&paths) diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index 4a40c02c30..bfe0479fea 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -114,10 +114,11 @@ bool ExPolygon::contains(const Polylines &polylines) const bool ExPolygon::contains(const Point &point) const { - if (!this->contour.contains(point)) return false; - for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { - if (it->contains(point)) return false; - } + if (! this->contour.contains(point)) + return false; + for (const Polygon &hole : this->holes) + if (hole.contains(point)) + return false; return true; } @@ -367,6 +368,57 @@ extern std::vector get_extents_vector(const ExPolygons &polygons) return out; } +bool has_duplicate_points(const ExPolygon &expoly) +{ +#if 1 + // Check globally. + size_t cnt = expoly.contour.points.size(); + for (const Polygon &hole : expoly.holes) + cnt += hole.points.size(); + std::vector allpts; + allpts.reserve(cnt); + allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); + for (const Polygon &hole : expoly.holes) + allpts.insert(allpts.end(), hole.points.begin(), hole.points.end()); + return has_duplicate_points(std::move(allpts)); +#else + // Check per contour. + if (has_duplicate_points(expoly.contour)) + return true; + for (const Polygon &hole : expoly.holes) + if (has_duplicate_points(hole)) + return true; + return false; +#endif +} + +bool has_duplicate_points(const ExPolygons &expolys) +{ +#if 1 + // Check globally. + size_t cnt = 0; + for (const ExPolygon &expoly : expolys) { + cnt += expoly.contour.points.size(); + for (const Polygon &hole : expoly.holes) + cnt += hole.points.size(); + } + std::vector allpts; + allpts.reserve(cnt); + for (const ExPolygon &expoly : expolys) { + allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); + for (const Polygon &hole : expoly.holes) + allpts.insert(allpts.end(), hole.points.begin(), hole.points.end()); + } + return has_duplicate_points(std::move(allpts)); +#else + // Check per contour. + for (const ExPolygon &expoly : expolys) + if (has_duplicate_points(expoly)) + return true; + return false; +#endif +} + bool remove_sticks(ExPolygon &poly) { return remove_sticks(poly.contour) || remove_sticks(poly.holes); diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 464310ac00..6f38846736 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -351,20 +351,24 @@ inline ExPolygons expolygons_simplify(const ExPolygons &expolys, double toleranc return out; } -extern BoundingBox get_extents(const ExPolygon &expolygon); -extern BoundingBox get_extents(const ExPolygons &expolygons); -extern BoundingBox get_extents_rotated(const ExPolygon &poly, double angle); -extern BoundingBox get_extents_rotated(const ExPolygons &polygons, double angle); -extern std::vector get_extents_vector(const ExPolygons &polygons); +BoundingBox get_extents(const ExPolygon &expolygon); +BoundingBox get_extents(const ExPolygons &expolygons); +BoundingBox get_extents_rotated(const ExPolygon &poly, double angle); +BoundingBox get_extents_rotated(const ExPolygons &polygons, double angle); +std::vector get_extents_vector(const ExPolygons &polygons); -extern bool remove_sticks(ExPolygon &poly); -extern void keep_largest_contour_only(ExPolygons &polygons); +// Test for duplicate points. The points are copied, sorted and checked for duplicates globally. +bool has_duplicate_points(const ExPolygon &expoly); +bool has_duplicate_points(const ExPolygons &expolys); + +bool remove_sticks(ExPolygon &poly); +void keep_largest_contour_only(ExPolygons &polygons); inline double area(const ExPolygon &poly) { return poly.area(); } inline double area(const ExPolygons &polys) { double s = 0.; for (auto &p : polys) s += p.area(); return s; } // Removes all expolygons smaller than min_area and also removes all holes smaller than min_area -extern bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area); +bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area); } // namespace Slic3r diff --git a/src/libslic3r/Point.cpp b/src/libslic3r/Point.cpp index 7f351d2598..b1f3a74bb0 100644 --- a/src/libslic3r/Point.cpp +++ b/src/libslic3r/Point.cpp @@ -179,6 +179,15 @@ Point Point::projection_onto(const Line &line) const return ((line.a - *this).cast().squaredNorm() < (line.b - *this).cast().squaredNorm()) ? line.a : line.b; } +bool has_duplicate_points(std::vector &&pts) +{ + std::sort(pts.begin(), pts.end()); + for (size_t i = 1; i < pts.size(); ++ i) + if (pts[i - 1] == pts[i]) + return true; + return false; +} + BoundingBox get_extents(const Points &pts) { return BoundingBox(pts); diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index 21eb48c2ee..499ab073d4 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -211,8 +211,34 @@ inline Point lerp(const Point &a, const Point &b, double t) return ((1. - t) * a.cast() + t * b.cast()).cast(); } -extern BoundingBox get_extents(const Points &pts); -extern BoundingBox get_extents(const std::vector &pts); +BoundingBox get_extents(const Points &pts); +BoundingBox get_extents(const std::vector &pts); + +// Test for duplicate points in a vector of points. +// The points are copied, sorted and checked for duplicates globally. +bool has_duplicate_points(std::vector &&pts); +inline bool has_duplicate_points(const std::vector &pts) +{ + std::vector cpy = pts; + return has_duplicate_points(std::move(cpy)); +} + +// Test for duplicate points in a vector of points. +// Only successive points are checked for equality. +inline bool has_duplicate_successive_points(const std::vector &pts) +{ + for (size_t i = 1; i < pts.size(); ++ i) + if (pts[i - 1] == pts[i]) + return true; + return false; +} + +// Test for duplicate points in a vector of points. +// Only successive points are checked for equality. Additionally, first and last points are compared for equality. +inline bool has_duplicate_successive_points_closed(const std::vector &pts) +{ + return has_duplicate_successive_points(pts) || (pts.size() >= 2 && pts.front() == pts.back()); +} namespace int128 { // Exact orientation predicate, diff --git a/src/libslic3r/Polygon.cpp b/src/libslic3r/Polygon.cpp index 5b180afcac..42a6cc2095 100644 --- a/src/libslic3r/Polygon.cpp +++ b/src/libslic3r/Polygon.cpp @@ -334,6 +334,27 @@ extern std::vector get_extents_vector(const Polygons &polygons) return out; } +bool has_duplicate_points(const Polygons &polys) +{ +#if 1 + // Check globally. + size_t cnt = 0; + for (const Polygon &poly : polys) + cnt += poly.points.size(); + std::vector allpts; + allpts.reserve(cnt); + for (const Polygon &poly : polys) + allpts.insert(allpts.end(), poly.points.begin(), poly.points.end()); + return has_duplicate_points(std::move(allpts)); +#else + // Check per contour. + for (const Polygon &poly : polys) + if (has_duplicate_points(poly)) + return true; + return false; +#endif +} + static inline bool is_stick(const Point &p1, const Point &p2, const Point &p3) { Point v1 = p2 - p1; diff --git a/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp index 3c46a564b2..29800a31d4 100644 --- a/src/libslic3r/Polygon.hpp +++ b/src/libslic3r/Polygon.hpp @@ -78,11 +78,16 @@ public: inline bool operator==(const Polygon &lhs, const Polygon &rhs) { return lhs.points == rhs.points; } inline bool operator!=(const Polygon &lhs, const Polygon &rhs) { return lhs.points != rhs.points; } -extern BoundingBox get_extents(const Polygon &poly); -extern BoundingBox get_extents(const Polygons &polygons); -extern BoundingBox get_extents_rotated(const Polygon &poly, double angle); -extern BoundingBox get_extents_rotated(const Polygons &polygons, double angle); -extern std::vector get_extents_vector(const Polygons &polygons); +BoundingBox get_extents(const Polygon &poly); +BoundingBox get_extents(const Polygons &polygons); +BoundingBox get_extents_rotated(const Polygon &poly, double angle); +BoundingBox get_extents_rotated(const Polygons &polygons, double angle); +std::vector get_extents_vector(const Polygons &polygons); + +// Test for duplicate points. The points are copied, sorted and checked for duplicates globally. +inline bool has_duplicate_points(Polygon &&poly) { return has_duplicate_points(std::move(poly.points)); } +inline bool has_duplicate_points(const Polygon &poly) { return has_duplicate_points(poly.points); } +bool has_duplicate_points(const Polygons &polys); inline double total_length(const Polygons &polylines) { double total = 0; @@ -102,19 +107,19 @@ inline double area(const Polygons &polys) } // Remove sticks (tentacles with zero area) from the polygon. -extern bool remove_sticks(Polygon &poly); -extern bool remove_sticks(Polygons &polys); +bool remove_sticks(Polygon &poly); +bool remove_sticks(Polygons &polys); // Remove polygons with less than 3 edges. -extern bool remove_degenerate(Polygons &polys); -extern bool remove_small(Polygons &polys, double min_area); -extern void remove_collinear(Polygon &poly); -extern void remove_collinear(Polygons &polys); +bool remove_degenerate(Polygons &polys); +bool remove_small(Polygons &polys, double min_area); +void remove_collinear(Polygon &poly); +void remove_collinear(Polygons &polys); // Append a vector of polygons at the end of another vector of polygons. -inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); } +inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); } -inline void polygons_append(Polygons &dst, Polygons &&src) +inline void polygons_append(Polygons &dst, Polygons &&src) { if (dst.empty()) { dst = std::move(src); From 6b25a9c8367fc3f16536248f9dd308b6cbe14265 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 24 Sep 2021 09:58:17 +0200 Subject: [PATCH 08/28] Fixed volume transformations in SLA: Volume transformations were ignored in SLA mode. This did not matter for plain STLs and PS own 3MF, because in those cases, the volume trafo was identity. Importing a 3rd party 3MF leads to issues with support/holes placement and generation. Fixes #6100 and #6744. --- src/libslic3r/SLA/ReprojectPointsOnMesh.hpp | 21 +++++++++--- src/libslic3r/SLAPrint.cpp | 8 +++-- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 35 +++++++++++++------- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 35 +++++++++++++------- 4 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp b/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp index 3ad7d62b1e..3ac3ff0451 100644 --- a/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp +++ b/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp @@ -35,11 +35,24 @@ inline void reproject_points_and_holes(ModelObject *object) TriangleMesh rmsh = object->raw_mesh(); IndexedMesh emesh{rmsh}; - if (has_sppoints) - reproject_support_points(emesh, object->sla_support_points); + const Transform3f& tr = object->volumes.front()->get_matrix().cast(); - if (has_holes) - reproject_support_points(emesh, object->sla_drain_holes); + if (has_sppoints) { + SupportPoints transformed_points = object->sla_support_points; + for (SupportPoint& pt : transformed_points) + pt.pos = tr * pt.pos; + reproject_support_points(emesh, transformed_points); + } + + if (has_holes) { + DrainHoles transformed_holes = object->sla_drain_holes; + for (DrainHole& hole : transformed_holes) { + // Hole normals are not transformed here, but the reprojection + // does not use them. + hole.pos = tr * hole.pos; + } + reproject_support_points(emesh, transformed_holes); + } } }} diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index a09f5ea98d..f2ca174d7f 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1167,7 +1167,9 @@ sla::SupportPoints SLAPrintObject::transformed_support_points() const { assert(m_model_object != nullptr); auto spts = m_model_object->sla_support_points; - auto tr = trafo().cast(); + + auto tr = (trafo() * m_model_object->volumes.front()->get_transformation().get_matrix()).cast(); + for (sla::SupportPoint& suppt : spts) { suppt.pos = tr * suppt.pos; } @@ -1179,8 +1181,8 @@ sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const { assert(m_model_object != nullptr); auto pts = m_model_object->sla_drain_holes; - auto tr = trafo().cast(); - auto sc = m_model_object->instances.front()->get_scaling_factor().cast(); + Transform3f tr = (trafo() * m_model_object->volumes.front()->get_matrix()).cast(); + Vec3f sc = Geometry::Transformation(tr.cast()).get_scaling_factor().cast(); for (sla::DrainHole &hl : pts) { hl.pos = tr * hl.pos; hl.normal = tr * hl.normal - tr.translation(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 17630e5c68..84a12c7a4d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -106,9 +106,13 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons shader->start_using(); ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); - const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()]; + const ModelVolume* mv = mo->volumes.front(); + Geometry::Transformation transformation(mi->get_transformation() * mv->get_transformation()); + + const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = transformation.get_matrix(); glsafe(::glPushMatrix()); glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); @@ -117,6 +121,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons std::array render_color; const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; size_t cache_size = drain_holes.size(); + const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); for (size_t i = 0; i < cache_size; ++i) { const sla::DrainHole& drain_hole = drain_holes[i]; @@ -184,13 +189,13 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const if (m_c->object_clipper()->get_position() == 0.) return false; - auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); - const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; - const Transform3d& trafo = mi->get_transformation().get_matrix(); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[active_inst]; + const Transform3d trafo = (mi->get_transformation() * mo->volumes.front()->get_transformation()).get_matrix(); Vec3d transformed_point = trafo * point; - transformed_point(2) += sel_info->get_sla_shift(); + transformed_point(2) += m_c->selection_info()->get_sla_shift(); return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point); } @@ -205,9 +210,12 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trafo = volume->get_instance_transformation(); - trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; + const ModelVolume* mv = mo->volumes.front(); + + Transform3d trafo = mi->get_transformation().get_matrix() * mv->get_matrix(); + trafo.pretranslate(Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane(); @@ -217,7 +225,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairraycaster()->raycaster()->unproject_on_mesh( mouse_pos, - trafo.get_matrix(), + trafo, camera, hit, normal, @@ -307,8 +315,11 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos GLSelectionRectangle::EState rectangle_status = m_selection_rectangle.get_state(); // First collect positions of all the points in world coordinates. - Geometry::Transformation trafo = mo->instances[active_inst]->get_transformation(); + const ModelInstance* mi = mo->instances[active_inst]; + const ModelVolume* mv = mo->volumes.front(); + Geometry::Transformation trafo(mi->get_transformation() * mv->get_transformation()); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + std::vector points; for (unsigned int i=0; isla_drain_holes.size(); ++i) points.push_back(trafo.get_matrix() * mo->sla_drain_holes[i].pos.cast()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index a50c503b9c..01fa162e11 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -127,9 +127,13 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) shader->stop_using(); }); - const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()]; + const ModelVolume* mv = mo->volumes.front(); + Geometry::Transformation transformation(mi->get_transformation() * mv->get_transformation()); + + const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = transformation.get_matrix(); float z_shift = m_c->selection_info()->get_sla_shift(); glsafe(::glPushMatrix()); @@ -137,6 +141,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glMultMatrixd(instance_matrix.data())); std::array render_color; + const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); for (size_t i = 0; i < cache_size; ++i) { const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false; @@ -265,13 +270,13 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const if (m_c->object_clipper()->get_position() == 0.) return false; - auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); - const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; - const Transform3d& trafo = mi->get_transformation().get_matrix(); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[active_inst]; + const Transform3d trafo = (mi->get_transformation() * mo->volumes.front()->get_transformation()).get_matrix(); Vec3d transformed_point = trafo * point; - transformed_point(2) += sel_info->get_sla_shift(); + transformed_point(2) += m_c->selection_info()->get_sla_shift(); return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point); } @@ -286,9 +291,12 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trafo = volume->get_instance_transformation(); - trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + const ModelObject* mo = m_c->selection_info()->model_object(); + const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; + const ModelVolume* mv = mo->volumes.front(); + + Transform3d trafo = mi->get_transformation().get_matrix() * mv->get_matrix(); + trafo.pretranslate(Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane(); @@ -298,7 +306,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairraycaster()->raycaster()->unproject_on_mesh( mouse_pos, - trafo.get_matrix(), + trafo, camera, hit, normal, @@ -388,8 +396,11 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous GLSelectionRectangle::EState rectangle_status = m_selection_rectangle.get_state(); // First collect positions of all the points in world coordinates. - Geometry::Transformation trafo = mo->instances[active_inst]->get_transformation(); + const ModelInstance* mi = mo->instances[active_inst]; + const ModelVolume* mv = mo->volumes.front(); + Geometry::Transformation trafo(mi->get_transformation() * mv->get_transformation()); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + std::vector points; for (unsigned int i=0; i()); From 6a5feb818f6003a3ad9228f095730cb50b97d480 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 24 Sep 2021 13:01:16 +0200 Subject: [PATCH 09/28] Revert "Fixed volume transformations in SLA:": The fix is not complete, it is better not to break it more than it was. This reverts commit 6b25a9c8367fc3f16536248f9dd308b6cbe14265. --- src/libslic3r/SLA/ReprojectPointsOnMesh.hpp | 21 +++--------- src/libslic3r/SLAPrint.cpp | 8 ++--- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 35 +++++++------------- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 35 +++++++------------- 4 files changed, 31 insertions(+), 68 deletions(-) diff --git a/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp b/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp index 3ac3ff0451..3ad7d62b1e 100644 --- a/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp +++ b/src/libslic3r/SLA/ReprojectPointsOnMesh.hpp @@ -35,24 +35,11 @@ inline void reproject_points_and_holes(ModelObject *object) TriangleMesh rmsh = object->raw_mesh(); IndexedMesh emesh{rmsh}; - const Transform3f& tr = object->volumes.front()->get_matrix().cast(); + if (has_sppoints) + reproject_support_points(emesh, object->sla_support_points); - if (has_sppoints) { - SupportPoints transformed_points = object->sla_support_points; - for (SupportPoint& pt : transformed_points) - pt.pos = tr * pt.pos; - reproject_support_points(emesh, transformed_points); - } - - if (has_holes) { - DrainHoles transformed_holes = object->sla_drain_holes; - for (DrainHole& hole : transformed_holes) { - // Hole normals are not transformed here, but the reprojection - // does not use them. - hole.pos = tr * hole.pos; - } - reproject_support_points(emesh, transformed_holes); - } + if (has_holes) + reproject_support_points(emesh, object->sla_drain_holes); } }} diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index f2ca174d7f..a09f5ea98d 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1167,9 +1167,7 @@ sla::SupportPoints SLAPrintObject::transformed_support_points() const { assert(m_model_object != nullptr); auto spts = m_model_object->sla_support_points; - - auto tr = (trafo() * m_model_object->volumes.front()->get_transformation().get_matrix()).cast(); - + auto tr = trafo().cast(); for (sla::SupportPoint& suppt : spts) { suppt.pos = tr * suppt.pos; } @@ -1181,8 +1179,8 @@ sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const { assert(m_model_object != nullptr); auto pts = m_model_object->sla_drain_holes; - Transform3f tr = (trafo() * m_model_object->volumes.front()->get_matrix()).cast(); - Vec3f sc = Geometry::Transformation(tr.cast()).get_scaling_factor().cast(); + auto tr = trafo().cast(); + auto sc = m_model_object->instances.front()->get_scaling_factor().cast(); for (sla::DrainHole &hl : pts) { hl.pos = tr * hl.pos; hl.normal = tr * hl.normal - tr.translation(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 84a12c7a4d..17630e5c68 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -106,13 +106,9 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons shader->start_using(); ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()]; - const ModelVolume* mv = mo->volumes.front(); - Geometry::Transformation transformation(mi->get_transformation() * mv->get_transformation()); - - const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = transformation.get_matrix(); + const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); + const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); glsafe(::glPushMatrix()); glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); @@ -121,7 +117,6 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons std::array render_color; const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; size_t cache_size = drain_holes.size(); - const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); for (size_t i = 0; i < cache_size; ++i) { const sla::DrainHole& drain_hole = drain_holes[i]; @@ -189,13 +184,13 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const if (m_c->object_clipper()->get_position() == 0.) return false; + auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[active_inst]; - const Transform3d trafo = (mi->get_transformation() * mo->volumes.front()->get_transformation()).get_matrix(); + const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; + const Transform3d& trafo = mi->get_transformation().get_matrix(); Vec3d transformed_point = trafo * point; - transformed_point(2) += m_c->selection_info()->get_sla_shift(); + transformed_point(2) += sel_info->get_sla_shift(); return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point); } @@ -210,12 +205,9 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; - const ModelVolume* mv = mo->volumes.front(); - - Transform3d trafo = mi->get_transformation().get_matrix() * mv->get_matrix(); - trafo.pretranslate(Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + Geometry::Transformation trafo = volume->get_instance_transformation(); + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane(); @@ -225,7 +217,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairraycaster()->raycaster()->unproject_on_mesh( mouse_pos, - trafo, + trafo.get_matrix(), camera, hit, normal, @@ -315,11 +307,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos GLSelectionRectangle::EState rectangle_status = m_selection_rectangle.get_state(); // First collect positions of all the points in world coordinates. - const ModelInstance* mi = mo->instances[active_inst]; - const ModelVolume* mv = mo->volumes.front(); - Geometry::Transformation trafo(mi->get_transformation() * mv->get_transformation()); + Geometry::Transformation trafo = mo->instances[active_inst]->get_transformation(); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); - std::vector points; for (unsigned int i=0; isla_drain_holes.size(); ++i) points.push_back(trafo.get_matrix() * mo->sla_drain_holes[i].pos.cast()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 01fa162e11..a50c503b9c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -127,13 +127,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) shader->stop_using(); }); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()]; - const ModelVolume* mv = mo->volumes.front(); - Geometry::Transformation transformation(mi->get_transformation() * mv->get_transformation()); - - const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = transformation.get_matrix(); + const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); + const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); float z_shift = m_c->selection_info()->get_sla_shift(); glsafe(::glPushMatrix()); @@ -141,7 +137,6 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glMultMatrixd(instance_matrix.data())); std::array render_color; - const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); for (size_t i = 0; i < cache_size; ++i) { const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false; @@ -270,13 +265,13 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const if (m_c->object_clipper()->get_position() == 0.) return false; + auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[active_inst]; - const Transform3d trafo = (mi->get_transformation() * mo->volumes.front()->get_transformation()).get_matrix(); + const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; + const Transform3d& trafo = mi->get_transformation().get_matrix(); Vec3d transformed_point = trafo * point; - transformed_point(2) += m_c->selection_info()->get_sla_shift(); + transformed_point(2) += sel_info->get_sla_shift(); return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point); } @@ -291,12 +286,9 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; - const ModelVolume* mv = mo->volumes.front(); - - Transform3d trafo = mi->get_transformation().get_matrix() * mv->get_matrix(); - trafo.pretranslate(Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + Geometry::Transformation trafo = volume->get_instance_transformation(); + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane(); @@ -306,7 +298,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairraycaster()->raycaster()->unproject_on_mesh( mouse_pos, - trafo, + trafo.get_matrix(), camera, hit, normal, @@ -396,11 +388,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous GLSelectionRectangle::EState rectangle_status = m_selection_rectangle.get_state(); // First collect positions of all the points in world coordinates. - const ModelInstance* mi = mo->instances[active_inst]; - const ModelVolume* mv = mo->volumes.front(); - Geometry::Transformation trafo(mi->get_transformation() * mv->get_transformation()); + Geometry::Transformation trafo = mo->instances[active_inst]->get_transformation(); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); - std::vector points; for (unsigned int i=0; i()); From 2356c303566b7b8ebcd8a8d8f66caca797eebe75 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 24 Sep 2021 13:10:23 +0200 Subject: [PATCH 10/28] Bumped up version number --- version.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.inc b/version.inc index d981d620ab..b7e941bb4d 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.4.0-alpha1") +set(SLIC3R_VERSION "2.4.0-alpha2") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_RC_VERSION "2,4,0,0") set(SLIC3R_RC_VERSION_DOTS "2.4.0.0") From 117df134f643ab2f62b6b955de36ebe6740e7eb3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 09:45:54 +0200 Subject: [PATCH 11/28] #7010 - Fixed import from 3mf containing modifiers crossing the printbed --- src/slic3r/GUI/Plater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a93a9d5e13..6404dbb6d6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2438,7 +2438,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ for (ModelObject* model_object : model.objects) { if (!type_3mf && !type_zip_amf) model_object->center_around_origin(false); - model_object->ensure_on_bed(is_project_file); + model_object->ensure_on_bed(is_project_file || type_3mf || type_zip_amf); } // check multi-part object adding for the SLA-printing @@ -2455,7 +2455,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (one_by_one) { if (type_3mf && !is_project_file) model.center_instances_around_point(bed_shape_bb().center()); - auto loaded_idxs = load_model_objects(model.objects, is_project_file); + auto loaded_idxs = load_model_objects(model.objects, is_project_file || type_3mf || type_zip_amf); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. From 33eba4aea65f42f5583ad3b1570227609a065cd0 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 21 Sep 2021 14:26:50 +0200 Subject: [PATCH 12/28] Rename SLAPrinter interface to SLAArchive as it makes more sense. --- src/libslic3r/Format/SL1.hpp | 2 +- src/libslic3r/SLAPrint.cpp | 2 +- src/libslic3r/SLAPrint.hpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index 2c7e1edc19..c2aef30f4c 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -8,7 +8,7 @@ namespace Slic3r { -class SL1Archive: public SLAPrinter { +class SL1Archive: public SLAArchive { SLAPrinterConfig m_cfg; protected: diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index a09f5ea98d..7899d173e1 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -670,7 +670,7 @@ std::string SLAPrint::validate(std::string*) const return ""; } -void SLAPrint::set_printer(SLAPrinter *arch) +void SLAPrint::set_printer(SLAArchive *arch) { invalidate_step(slapsRasterize); m_printer = arch; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e11926c7ea..deaabbe19a 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -387,7 +387,7 @@ struct SLAPrintStatistics } }; -class SLAPrinter { +class SLAArchive { protected: std::vector m_layers; @@ -395,7 +395,7 @@ protected: virtual sla::RasterEncoder get_encoder() const = 0; public: - virtual ~SLAPrinter() = default; + virtual ~SLAArchive() = default; virtual void apply(const SLAPrinterConfig &cfg) = 0; @@ -526,7 +526,7 @@ public: // TODO: use this structure for the preview in the future. const std::vector& print_layers() const { return m_printer_input; } - void set_printer(SLAPrinter *archiver); + void set_printer(SLAArchive *archiver); private: @@ -548,7 +548,7 @@ private: std::vector m_printer_input; // The archive object which collects the raster images after slicing - SLAPrinter *m_printer = nullptr; + SLAArchive *m_printer = nullptr; // Estimated print time, material consumed. SLAPrintStatistics m_print_statistics; From 4d2bf8db0dc9133aeb515a8cd50c58af48b10b56 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 21 Sep 2021 14:29:27 +0200 Subject: [PATCH 13/28] Switch to current SLA profile if an imported archive doesn't contain it. Send a warning notification if this happens. Also,if there is no current SLA profile initialized, an error message will tell the user to switch to an SLA profile before importing. fixes #6915 --- src/libslic3r/Format/SL1.cpp | 24 +++++++++++++++++------- src/libslic3r/Format/SL1.hpp | 2 ++ src/slic3r/GUI/Jobs/SLAImportJob.cpp | 24 ++++++++++++++++++------ 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index e2ef801f27..4ddc584ba5 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -203,7 +203,7 @@ RasterParams get_raster_params(const DynamicPrintConfig &cfg) if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h || !opt_mirror_x || !opt_mirror_y || !opt_orient) - throw Slic3r::FileIOError("Invalid SL1 / SL1S file"); + throw MissingProfileError("Invalid SL1 / SL1S file"); RasterParams rstp; @@ -229,7 +229,7 @@ SliceParams get_slice_params(const DynamicPrintConfig &cfg) auto *opt_init_layerh = cfg.option("initial_layer_height"); if (!opt_layerh || !opt_init_layerh) - throw Slic3r::FileIOError("Invalid SL1 / SL1S file"); + throw MissingProfileError("Invalid SL1 / SL1S file"); return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()}; } @@ -293,24 +293,34 @@ ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrint return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); } +// If the profile is missing from the archive (older PS versions did not have +// it), profile_out's initial value will be used as fallback. profile_out will be empty on +// function return if the archive did not contain any profile. ConfigSubstitutions import_sla_archive( const std::string & zipfname, Vec2i windowsize, indexed_triangle_set & out, - DynamicPrintConfig & profile, + DynamicPrintConfig & profile_out, std::function progr) { // Ensure minimum window size for marching squares windowsize.x() = std::max(2, windowsize.x()); windowsize.y() = std::max(2, windowsize.y()); - ArchiveData arch = extract_sla_archive(zipfname, "thumbnail"); - ConfigSubstitutions config_substitutions = profile.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); + std::string exclude_entries{"thumbnail"}; + ArchiveData arch = extract_sla_archive(zipfname, exclude_entries); + DynamicPrintConfig profile_in, profile_use; + ConfigSubstitutions config_substitutions = profile_in.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); - RasterParams rstp = get_raster_params(profile); + // If the archive contains an empty profile, use the one that was passed as output argument + // then replace it with the readed profile to report that it was empty. + profile_use = profile_in.empty() ? profile_out : profile_in; + profile_out = profile_in; + + RasterParams rstp = get_raster_params(profile_use); rstp.win = {windowsize.y(), windowsize.x()}; - SliceParams slicp = get_slice_params(profile); + SliceParams slicp = get_slice_params(profile_use); std::vector slices = extract_slices_from_sla_archive(arch, rstp, progr); diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index c2aef30f4c..7f4356b12c 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -57,6 +57,8 @@ inline ConfigSubstitutions import_sla_archive( return import_sla_archive(zipfname, windowsize, out, profile, progr); } +class MissingProfileError : public RuntimeError { using RuntimeError::RuntimeError; }; + } // namespace Slic3r::sla #endif // ARCHIVETRAITS_HPP diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index e632028622..3d611ffc3c 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" +#include "slic3r/GUI/NotificationManager.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" @@ -144,16 +145,16 @@ void SLAImportJob::process() try { switch (p->sel) { case Sel::modelAndProfile: - p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr); - break; case Sel::modelOnly: - p->config_substitutions = import_sla_archive(path, p->win, p->mesh, progr); + p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr); break; case Sel::profileOnly: p->config_substitutions = import_sla_archive(path, p->profile); break; } - + } catch (MissingProfileError &) { + p->err = _L("The archive doesn't contain any profile data. Try to import after switching " + "to an SLA profile that can be used as fallback.").ToStdString(); } catch (std::exception &ex) { p->err = ex.what(); } @@ -166,7 +167,7 @@ void SLAImportJob::reset() { p->sel = Sel::modelAndProfile; p->mesh = {}; - p->profile = {}; + p->profile = m_plater->sla_print().full_print_config(); p->win = {2, 2}; p->path.Clear(); } @@ -202,7 +203,18 @@ void SLAImportJob::finalize() std::string name = wxFileName(p->path).GetName().ToUTF8().data(); - if (!p->profile.empty()) { + if (p->profile.empty()) { + m_plater->get_notification_manager()->push_notification( + NotificationType::CustomNotification, + NotificationManager::NotificationLevel::WarningNotificationLevel, + _L("Loaded archive did not contain any profile data. " + "The current SLA profile was used as fallback.").ToStdString()); + } + + if (p->sel != Sel::modelOnly) { + if (p->profile.empty()) + p->profile = m_plater->sla_print().full_print_config(); + const ModelObjectPtrs& objects = p->plater->model().objects; for (auto object : objects) if (object->volumes.size() > 1) From 07e7e115901c80f282b06ea6b86bc56b28e1a02b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 27 Sep 2021 10:02:48 +0200 Subject: [PATCH 14/28] Fix of prusa-gcodeviewer changes modification time of the viewed gcode file #7005 This is a regression wrt. PrusaSlicer 2.4.0-alpha1 due to the G-code processing optimization and parallelization. Related to GCode Viewer changes files modified date in windows #5079 --- src/libslic3r/GCode/GCodeProcessor.cpp | 10 +++++++--- src/libslic3r/GCode/GCodeProcessor.hpp | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 4e731c8b4e..55c41f8fe4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1189,6 +1189,8 @@ static inline const char* remove_eols(const char *begin, const char *end) { return end; } +// Load a G-code into a stand-alone G-code viewer. +// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). void GCodeProcessor::process_file(const std::string& filename, std::function cancel_callback) { CNumericLocalesSetter locales_setter; @@ -1243,7 +1245,8 @@ void GCodeProcessor::process_file(const std::string& filename, std::functionprocess_gcode_line(line, true); }); - this->finalize(); + // Don't post-process the G-code to update time stamps. + this->finalize(false); } void GCodeProcessor::initialize(const std::string& filename) @@ -1269,7 +1272,7 @@ void GCodeProcessor::process_buffer(const std::string &buffer) }); } -void GCodeProcessor::finalize() +void GCodeProcessor::finalize(bool post_process) { // update width/height of wipe moves for (MoveVertex& move : m_result.moves) { @@ -1299,7 +1302,8 @@ void GCodeProcessor::finalize() m_width_compare.output(); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING - m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); + if (post_process) + m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); #if ENABLE_GCODE_VIEWER_STATISTICS m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 5af0403071..0639567ea4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -579,14 +579,14 @@ namespace Slic3r { const Result& get_result() const { return m_result; } Result&& extract_result() { return std::move(m_result); } - // Process the gcode contained in the file with the given filename + // Load a G-code into a stand-alone G-code viewer. // throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). void process_file(const std::string& filename, std::function cancel_callback = nullptr); // Streaming interface, for processing G-codes just generated by PrusaSlicer in a pipelined fashion. void initialize(const std::string& filename); void process_buffer(const std::string& buffer); - void finalize(); + void finalize(bool post_process); float get_time(PrintEstimatedStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; From 43470af0c605d2b9baa03500e70ea39cda5403e5 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 27 Sep 2021 10:07:29 +0200 Subject: [PATCH 15/28] Fix of "About" screen still shows 2020 at the copyright notice (#7018) --- src/libslic3r/GCode.cpp | 3 ++- src/platform/msw/PrusaSlicer-gcodeviewer.rc.in | 2 +- src/platform/msw/PrusaSlicer.rc.in | 2 +- src/platform/osx/Info.plist.in | 2 +- src/slic3r/GUI/AboutDialog.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index bff894558a..ff0a7c0273 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -784,7 +784,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re } BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info(); - m_processor.finalize(); + // Post-process the G-code to update time stamps. + m_processor.finalize(true); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics); if (result != nullptr) { diff --git a/src/platform/msw/PrusaSlicer-gcodeviewer.rc.in b/src/platform/msw/PrusaSlicer-gcodeviewer.rc.in index eed737cb77..518f6b7b60 100644 --- a/src/platform/msw/PrusaSlicer-gcodeviewer.rc.in +++ b/src/platform/msw/PrusaSlicer-gcodeviewer.rc.in @@ -12,7 +12,7 @@ PRODUCTVERSION @SLIC3R_RC_VERSION@ VALUE "ProductName", "@SLIC3R_APP_NAME@ G-code Viewer" VALUE "ProductVersion", "@SLIC3R_BUILD_ID@" VALUE "InternalName", "@SLIC3R_APP_NAME@ G-code Viewer" - VALUE "LegalCopyright", "Copyright \251 2016-2020 Prusa Research, \251 2011-2018 Alessandro Ranellucci" + VALUE "LegalCopyright", "Copyright \251 2016-2021 Prusa Research, \251 2011-2018 Alessandro Ranellucci" VALUE "OriginalFilename", "prusa-gcodeviewer.exe" } } diff --git a/src/platform/msw/PrusaSlicer.rc.in b/src/platform/msw/PrusaSlicer.rc.in index a4520c6d73..d7f860204d 100644 --- a/src/platform/msw/PrusaSlicer.rc.in +++ b/src/platform/msw/PrusaSlicer.rc.in @@ -12,7 +12,7 @@ PRODUCTVERSION @SLIC3R_RC_VERSION@ VALUE "ProductName", "@SLIC3R_APP_NAME@" VALUE "ProductVersion", "@SLIC3R_BUILD_ID@" VALUE "InternalName", "@SLIC3R_APP_NAME@" - VALUE "LegalCopyright", "Copyright \251 2016-2020 Prusa Research, \251 2011-2018 Alessandro Ranellucci" + VALUE "LegalCopyright", "Copyright \251 2016-2021 Prusa Research, \251 2011-2018 Alessandro Ranellucci" VALUE "OriginalFilename", "prusa-slicer.exe" } } diff --git a/src/platform/osx/Info.plist.in b/src/platform/osx/Info.plist.in index 46858bb293..f1de1d24b6 100644 --- a/src/platform/osx/Info.plist.in +++ b/src/platform/osx/Info.plist.in @@ -5,7 +5,7 @@ CFBundleExecutable @SLIC3R_APP_KEY@ CFBundleGetInfoString - @SLIC3R_APP_NAME@ Copyright (C) 2011-2019 Alessandro Ranellucci, (C) 2016-2020 Prusa Reseach + @SLIC3R_APP_NAME@ Copyright (C) 2011-2019 Alessandro Ranellucci, (C) 2016-2021 Prusa Reseach CFBundleIconFile PrusaSlicer.icns CFBundleName diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index 2aae9270dc..a6b99a08ba 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -275,7 +275,7 @@ AboutDialog::AboutDialog() "" "" "" - "%4% © 2016-2020 Prusa Research.
" + "%4% © 2016-2021 Prusa Research.
" "%5% © 2011-2018 Alessandro Ranellucci.
" "Slic3r %6% " "%7%." From 7ca9024fca349696501b6d1a2a6b584517b3a538 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 11:22:36 +0200 Subject: [PATCH 16/28] #7008 - GCodeViewer - Fixed loading of gcodes generated by SuperSlicer --- src/libslic3r/Config.cpp | 6 +++- src/libslic3r/Config.hpp | 4 +++ src/libslic3r/GCode/GCodeProcessor.cpp | 45 ++++++++++++++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 6 ++++ src/libslic3r/Technologies.hpp | 9 ++++++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index ab58a43aa0..2d4780d0ec 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -740,7 +740,11 @@ ConfigSubstitutions ConfigBase::load(const boost::property_tree::ptree &tree, Fo } // Load the config keys from the given string. -static inline size_t load_from_gcode_string_legacy(ConfigBase &config, const char *str, ConfigSubstitutionContext &substitutions) +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT +size_t ConfigBase::load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions) +#else +static inline size_t load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions) +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT { if (str == nullptr) return 0; diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 6439e4632c..dd121c90af 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -2015,6 +2015,10 @@ public: // Set all the nullable values to nils. void null_nullables(); +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + static size_t load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions); +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + private: // Set a configuration value from a string. bool set_deserialize_raw(const t_config_option_key& opt_key_src, const std::string& value, ConfigSubstitutionContext& substitutions, bool append); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 55c41f8fe4..ea46cd3a5c 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -746,6 +746,9 @@ const std::vector> GCodeProces { EProducer::PrusaSlicer, "generated by PrusaSlicer" }, { EProducer::Slic3rPE, "generated by Slic3r Prusa Edition" }, { EProducer::Slic3r, "generated by Slic3r" }, +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + { EProducer::SuperSlicer, "generated by SuperSlicer" }, +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT { EProducer::Cura, "Cura_SteamEngine" }, { EProducer::Simplify3D, "G-Code generated by Simplify3D(R)" }, { EProducer::CraftWare, "CraftWare" }, @@ -1227,6 +1230,10 @@ void GCodeProcessor::process_file(const std::string& filename, std::function> GCodeProcessor::get_roles_time(Prin return ret; } +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT +ConfigSubstitutions load_from_superslicer_gcode_file(const std::string& filename, DynamicPrintConfig& config, ForwardCompatibilitySubstitutionRule compatibility_rule) +{ + // for reference, see: ConfigBase::load_from_gcode_file() + + boost::nowide::ifstream ifs(filename); + + auto header_end_pos = ifs.tellg(); + ConfigSubstitutionContext substitutions_ctxt(compatibility_rule); + size_t key_value_pairs = 0; + + ifs.seekg(0, ifs.end); + auto file_length = ifs.tellg(); + auto data_length = std::min(65535, file_length - header_end_pos); + ifs.seekg(file_length - data_length, ifs.beg); + std::vector data(size_t(data_length) + 1, 0); + ifs.read(data.data(), data_length); + ifs.close(); + key_value_pairs = ConfigBase::load_from_gcode_string_legacy(config, data.data(), substitutions_ctxt); + + if (key_value_pairs < 80) + throw Slic3r::RuntimeError(format("Suspiciously low number of configuration values extracted from %1%: %2%", filename, key_value_pairs)); + + return std::move(substitutions_ctxt.substitutions); +} + +void GCodeProcessor::apply_config_superslicer(const std::string& filename) +{ + DynamicPrintConfig config; + config.apply(FullPrintConfig::defaults()); + load_from_superslicer_gcode_file(filename, config, ForwardCompatibilitySubstitutionRule::EnableSilent); + apply_config(config); +} +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + std::vector GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const { return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? @@ -1849,6 +1891,9 @@ bool GCodeProcessor::process_producers_tags(const std::string_view comment) { case EProducer::Slic3rPE: case EProducer::Slic3r: +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + case EProducer::SuperSlicer: +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT case EProducer::PrusaSlicer: { return process_prusaslicer_tags(comment); } case EProducer::Cura: { return process_cura_tags(comment); } case EProducer::Simplify3D: { return process_simplify3d_tags(comment); } diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 0639567ea4..fce8882333 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -543,6 +543,9 @@ namespace Slic3r { PrusaSlicer, Slic3rPE, Slic3r, +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + SuperSlicer, +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT Cura, Simplify3D, CraftWare, @@ -599,6 +602,9 @@ namespace Slic3r { private: void apply_config(const DynamicPrintConfig& config); void apply_config_simplify3d(const std::string& filename); +#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT + void apply_config_superslicer(const std::string& filename); +#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled); // Process tags embedded into comments diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index e32f3cde70..350f6aedc5 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -64,4 +64,13 @@ #define ENABLE_FIX_SEAMS_SYNCH (1 && ENABLE_2_4_0_ALPHA2) +//==================== +// 2.4.0.alpha3 techs +//==================== +#define ENABLE_2_4_0_ALPHA3 1 + +// Enable fixing loading of gcode files generated with SuperSlicer in GCodeViewer +#define ENABLE_FIX_SUPERSLICER_GCODE_IMPORT (1 && ENABLE_2_4_0_ALPHA3) + + #endif // _prusaslicer_technologies_h_ From 721e396edcb81ed0dd767d9162531b3848eb4e7f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 11:35:58 +0200 Subject: [PATCH 17/28] #7016 - Fixed GCodeProcessor::process_M132() --- src/libslic3r/GCode/GCodeProcessor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index ea46cd3a5c..5726cf9bef 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2867,16 +2867,16 @@ void GCodeProcessor::process_M132(const GCodeReader::GCodeLine& line) // see: https://github.com/makerbot/s3g/blob/master/doc/GCodeProtocol.md // Using this command to reset the axis origin to zero helps in fixing: https://github.com/prusa3d/PrusaSlicer/issues/3082 - if (line.has_x()) + if (line.has('X')) m_origin[X] = 0.0f; - if (line.has_y()) + if (line.has('Y')) m_origin[Y] = 0.0f; - if (line.has_z()) + if (line.has('Z')) m_origin[Z] = 0.0f; - if (line.has_e()) + if (line.has('E')) m_origin[E] = 0.0f; } From 8ecdea152f4a38607062481fb13d45386afdaa45 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 12:08:26 +0200 Subject: [PATCH 18/28] Follow-up of 721e396edcb81ed0dd767d9162531b3848eb4e7f - Same fix applied to GCodeProcessor::process_G28() and GCodeProcessor::process_M402() --- src/libslic3r/GCode/GCodeProcessor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 5726cf9bef..5bfe51a479 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2723,15 +2723,15 @@ void GCodeProcessor::process_G28(const GCodeReader::GCodeLine& line) std::string_view cmd = line.cmd(); std::string new_line_raw = { cmd.data(), cmd.size() }; bool found = false; - if (line.has_x()) { + if (line.has('X')) { new_line_raw += " X0"; found = true; } - if (line.has_y()) { + if (line.has('Y')) { new_line_raw += " Y0"; found = true; } - if (line.has_z()) { + if (line.has('Z')) { new_line_raw += " Z0"; found = true; } @@ -3037,7 +3037,7 @@ void GCodeProcessor::process_M402(const GCodeReader::GCodeLine& line) // https://github.com/repetier/Repetier-Firmware/blob/master/src/ArduinoAVR/Repetier/Printer.cpp // void Printer::GoToMemoryPosition(bool x, bool y, bool z, bool e, float feed) - bool has_xyz = !(line.has_x() || line.has_y() || line.has_z()); + bool has_xyz = !(line.has('X') || line.has('Y') || line.has('Z')); float p = FLT_MAX; for (unsigned char a = X; a <= Z; ++a) { From 1196251d5133aeec4d20ae36bf4a8462bcb8baf4 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 12:33:26 +0200 Subject: [PATCH 19/28] #7015 - Fixed typo in AMFParserContext::endElement() --- src/libslic3r/Format/AMF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 9392485f62..f0807df514 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -598,7 +598,7 @@ void AMFParserContext::endElement(const char * /* name */) case NODE_TYPE_VERTEX: assert(m_object); // Parse the vertex data - m_object_vertices.emplace_back(float(atof(m_value[0].c_str())), float(atof(m_value[1].c_str())), float(atof(m_value[1].c_str()))); + m_object_vertices.emplace_back(float(atof(m_value[0].c_str())), float(atof(m_value[1].c_str())), float(atof(m_value[2].c_str()))); m_value[0].clear(); m_value[1].clear(); m_value[2].clear(); From 2483a9f036294897f074d966d210db3c44143625 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 13:02:56 +0200 Subject: [PATCH 20/28] Added missing include --- src/libslic3r/GCode/GCodeProcessor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 5bfe51a479..2397a17ff7 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2,6 +2,7 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/Print.hpp" #include "libslic3r/LocalesUtils.hpp" +#include "libslic3r/format.hpp" #include "GCodeProcessor.hpp" #include From 41dc265a45196fd6a8f2b79ac6e803f41cbe22f8 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 27 Sep 2021 14:10:53 +0200 Subject: [PATCH 21/28] WIP Undo / Redo and project state: Marking Undo / Redo snapshots with their purpose. --- src/slic3r/GUI/GLCanvas3D.cpp | 5 ++-- src/slic3r/GUI/GUI_ObjectList.cpp | 5 ++-- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 8 +++--- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 8 +++--- src/slic3r/GUI/Plater.cpp | 26 +++++++++++--------- src/slic3r/GUI/Plater.hpp | 10 ++++++++ src/slic3r/GUI/Selection.cpp | 17 +++++++------ src/slic3r/Utils/UndoRedo.cpp | 7 ++++++ src/slic3r/Utils/UndoRedo.hpp | 25 +++++++++++++++++-- 9 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 227e5ae4e5..97d176ac65 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -23,6 +23,7 @@ #include "slic3r/GUI/3DBed.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/MainFrame.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" @@ -6456,7 +6457,7 @@ void GLCanvas3D::_update_selection_from_hover() // the selection is going to be modified (Add) if (!contains_all) { - wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle"))); + wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle")), UndoRedo::SnapshotType::Selection); selection_changed = true; } } @@ -6471,7 +6472,7 @@ void GLCanvas3D::_update_selection_from_hover() // the selection is going to be modified (Remove) if (contains_any) { - wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle"))); + wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle")), UndoRedo::SnapshotType::Selection); selection_changed = true; } } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 1e290beae8..a980440e54 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -10,6 +10,7 @@ #include "BitmapComboBox.hpp" #include "GalleryDialog.hpp" #include "MainFrame.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include "OptionsGroup.hpp" #include "Tab.hpp" @@ -3455,7 +3456,7 @@ void ObjectList::update_selections_on_canvas() volume_idxs = selection.get_missing_volume_idxs_from(volume_idxs); if (volume_idxs.size() > 0) { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Remove from list"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Remove from list")), UndoRedo::SnapshotType::Selection); selection.remove_volumes(mode, volume_idxs); } } @@ -3463,7 +3464,7 @@ void ObjectList::update_selections_on_canvas() { // add volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs); - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Add from list"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Add from list")), UndoRedo::SnapshotType::Selection); selection.add_volumes(mode, volume_idxs, single_selection); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index ac9d7adcf1..474e316318 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Plater.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/Model.hpp" @@ -51,17 +52,18 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate) ? _u8L("Entering Paint-on supports") : _u8L("Entering Seam painting"); if (last_snapshot_name != str) - Plater::TakeSnapshot(plater, str); + Plater::TakeSnapshot(plater, str, UndoRedo::SnapshotType::EnteringGizmo); plater->enter_gizmos_stack(); m_internal_stack_active = true; } if (!activate && m_internal_stack_active) { - plater->leave_gizmos_stack(); + bool project_modified = 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) - Plater::TakeSnapshot(plater, str); + Plater::TakeSnapshot(plater, str, + project_modified ? UndoRedo::SnapshotType::LeavingGizmoWithAction : UndoRedo::SnapshotType::LeavingGizmoNoAction); m_internal_stack_active = false; } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 6d8ae36ab2..9a3bd5a426 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -4,6 +4,7 @@ #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/MainFrame.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include @@ -907,7 +908,7 @@ void GLGizmoSlaSupports::on_set_state() // data are not yet available, the CallAfter will postpone taking the // snapshot until they are. No, it does not feel right. wxGetApp().CallAfter([]() { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Entering SLA gizmo")); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Entering SLA gizmo"), UndoRedo::SnapshotType::EnteringGizmo); }); } @@ -925,8 +926,9 @@ void GLGizmoSlaSupports::on_set_state() } else { // we are actually shutting down - disable_editing_mode(); // so it is not active next time the gizmo opens - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Leaving SLA gizmo")); + bool project_modified = disable_editing_mode(); // so it is not active next time the gizmo opens + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Leaving SLA gizmo"), + project_modified ? UndoRedo::SnapshotType::LeavingGizmoWithAction : UndoRedo::SnapshotType::LeavingGizmoNo); m_normal_cache.clear(); m_old_mo_id = -1; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 60215484b8..760e429778 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1531,25 +1531,25 @@ struct Plater::priv void arrange() { - m->take_snapshot(_(L("Arrange"))); + m->take_snapshot(_L("Arrange")); start(m_arrange_id); } void fill_bed() { - m->take_snapshot(_(L("Fill bed"))); + m->take_snapshot(_L("Fill bed")); start(m_fill_bed_id); } void optimize_rotation() { - m->take_snapshot(_(L("Optimize Rotation"))); + m->take_snapshot(_L("Optimize Rotation")); start(m_rotoptimize_id); } void import_sla_arch() { - m->take_snapshot(_(L("Import SLA archive"))); + m->take_snapshot(_L("Import SLA archive")); start(m_sla_import_id); } @@ -1671,8 +1671,9 @@ struct Plater::priv void enter_gizmos_stack(); void leave_gizmos_stack(); - void take_snapshot(const std::string& snapshot_name); - void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } + void take_snapshot(const std::string& snapshot_name, UndoRedo::SnapshotType snapshot_type = UndoRedo::SnapshotType::Action); + void take_snapshot(const wxString& snapshot_name, UndoRedo::SnapshotType snapshot_type = UndoRedo::SnapshotType::Action) + { this->take_snapshot(std::string(snapshot_name.ToUTF8().data()), snapshot_type); } int get_active_snapshot_index(); void undo(); @@ -2046,7 +2047,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) } // Initialize the Undo / Redo stack with a first snapshot. - this->take_snapshot(_L("New Project")); + this->take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator); this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event."; @@ -2783,7 +2784,7 @@ void Plater::priv::delete_all_objects_from_model() void Plater::priv::reset() { - Plater::TakeSnapshot snapshot(q, _L("Reset Project")); + Plater::TakeSnapshot snapshot(q, _L("Reset Project"), UndoRedo::SnapshotType::ProjectSeparator); clear_warnings(); @@ -4425,12 +4426,13 @@ int Plater::priv::get_active_snapshot_index() return it - ss_stack.begin(); } -void Plater::priv::take_snapshot(const std::string& snapshot_name) +void Plater::priv::take_snapshot(const std::string& snapshot_name, const UndoRedo::SnapshotType snapshot_type) { if (m_prevent_snapshots > 0) return; assert(m_prevent_snapshots >= 0); UndoRedo::SnapshotData snapshot_data; + snapshot_data.snapshot_type = snapshot_type; snapshot_data.printer_technology = this->printer_technology; if (this->view3D->is_layers_editing_enabled()) snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; @@ -4702,7 +4704,7 @@ void Plater::new_project() return; p->select_view_3D("3D"); - take_snapshot(_L("New Project")); + take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator); Plater::SuppressSnapshots suppress(this); reset(); reset_project_dirty_initial_presets(); @@ -4727,7 +4729,7 @@ void Plater::load_project(const wxString& filename) return; // Take the Undo / Redo snapshot. - Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str())); + Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()), UndoRedo::SnapshotType::ProjectSeparator); p->reset(); @@ -5746,6 +5748,8 @@ void Plater::eject_drive() void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(snapshot_name); } void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); } +void Plater::take_snapshot(const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type) { p->take_snapshot(snapshot_name, snapshot_type); } +void Plater::take_snapshot(const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type) { p->take_snapshot(snapshot_name, snapshot_type); } void Plater::suppress_snapshots() { p->suppress_snapshots(); } void Plater::allow_snapshots() { p->allow_snapshots(); } void Plater::undo() { p->undo(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 3556756e23..d1bbf7097f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -37,6 +37,7 @@ using ModelInstancePtrs = std::vector; namespace UndoRedo { class Stack; + enum class SnapshotType : unsigned char; struct Snapshot; } @@ -241,6 +242,9 @@ public: void take_snapshot(const std::string &snapshot_name); void take_snapshot(const wxString &snapshot_name); + void take_snapshot(const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type); + void take_snapshot(const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type); + void undo(); void redo(); void undo_to(int selection); @@ -392,6 +396,12 @@ public: m_plater->take_snapshot(snapshot_name); m_plater->suppress_snapshots(); } + TakeSnapshot(Plater *plater, const wxString &snapshot_name, UndoRedo::SnapshotType snapshot_type) : m_plater(plater) + { + m_plater->take_snapshot(snapshot_name, snapshot_type); + m_plater->suppress_snapshots(); + } + ~TakeSnapshot() { m_plater->allow_snapshots(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index ba4577bfb0..a89a2f7ba4 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -10,6 +10,7 @@ #include "Gizmos/GLGizmoBase.hpp" #include "Camera.hpp" #include "Plater.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/LocalesUtils.hpp" #include "libslic3r/Model.hpp" @@ -162,7 +163,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec needs_reset |= is_any_modifier() && !volume->is_modifier; if (!already_contained || needs_reset) { - wxGetApp().plater()->take_snapshot(_L("Selection-Add")); + wxGetApp().plater()->take_snapshot(_L("Selection-Add"), UndoRedo::SnapshotType::Selection); if (needs_reset) clear(); @@ -203,7 +204,7 @@ void Selection::remove(unsigned int volume_idx) if (!contains_volume(volume_idx)) return; - wxGetApp().plater()->take_snapshot(_L("Selection-Remove")); + wxGetApp().plater()->take_snapshot(_L("Selection-Remove"), UndoRedo::SnapshotType::Selection); GLVolume* volume = (*m_volumes)[volume_idx]; @@ -235,7 +236,7 @@ void Selection::add_object(unsigned int object_idx, bool as_single_selection) (as_single_selection && matches(volume_idxs))) return; - wxGetApp().plater()->take_snapshot(_L("Selection-Add Object")); + wxGetApp().plater()->take_snapshot(_L("Selection-Add Object"), UndoRedo::SnapshotType::Selection); // resets the current list if needed if (as_single_selection) @@ -254,7 +255,7 @@ void Selection::remove_object(unsigned int object_idx) if (!m_valid) return; - wxGetApp().plater()->take_snapshot(_L("Selection-Remove Object")); + wxGetApp().plater()->take_snapshot(_L("Selection-Remove Object"), UndoRedo::SnapshotType::Selection); do_remove_object(object_idx); @@ -272,7 +273,7 @@ void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, (as_single_selection && matches(volume_idxs))) return; - wxGetApp().plater()->take_snapshot(_L("Selection-Add Instance")); + wxGetApp().plater()->take_snapshot(_L("Selection-Add Instance"), UndoRedo::SnapshotType::Selection); // resets the current list if needed if (as_single_selection) @@ -291,7 +292,7 @@ void Selection::remove_instance(unsigned int object_idx, unsigned int instance_i if (!m_valid) return; - wxGetApp().plater()->take_snapshot(_L("Selection-Remove Instance")); + wxGetApp().plater()->take_snapshot(_L("Selection-Remove Instance"), UndoRedo::SnapshotType::Selection); do_remove_instance(object_idx, instance_idx); @@ -388,7 +389,7 @@ void Selection::add_all() if ((unsigned int)m_list.size() == count) return; - wxGetApp().plater()->take_snapshot(_(L("Selection-Add All"))); + wxGetApp().plater()->take_snapshot(_(L("Selection-Add All")), UndoRedo::SnapshotType::Selection); m_mode = Instance; clear(); @@ -413,7 +414,7 @@ void Selection::remove_all() // Not taking the snapshot with non-empty Redo stack will likely be more confusing than losing the Redo stack. // Let's wait for user feedback. // if (!wxGetApp().plater()->can_redo()) - wxGetApp().plater()->take_snapshot(_L("Selection-Remove All")); + wxGetApp().plater()->take_snapshot(_L("Selection-Remove All"), UndoRedo::SnapshotType::Selection); m_mode = Instance; clear(); diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index 6d6753ea29..ad6c830e29 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -556,6 +556,12 @@ public: // Snapshot history (names with timestamps). const std::vector& snapshots() const { return m_snapshots; } + const Snapshot& snapshot(size_t time) const { + const auto it = std::lower_bound(m_snapshots.cbegin(), m_snapshots.cend(), UndoRedo::Snapshot(time)); + assert(it != m_snapshots.end() && it->timestamp == time); + return *it; + } + // Timestamp of the active snapshot. size_t active_snapshot_time() const { return m_active_snapshot_time; } bool temp_snapshot_active() const { return m_snapshots.back().timestamp == m_active_snapshot_time && ! m_snapshots.back().is_topmost_captured(); } @@ -1097,6 +1103,7 @@ bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, siz const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } const std::vector& Stack::snapshots() const { return pimpl->snapshots(); } +const Snapshot& Stack::snapshot(size_t time) const { return pimpl->snapshot(time); } size_t Stack::active_snapshot_time() const { return pimpl->active_snapshot_time(); } bool Stack::temp_snapshot_active() const { return pimpl->temp_snapshot_active(); } diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp index e120c4f790..d29c0e9796 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -24,6 +24,23 @@ namespace GUI { namespace UndoRedo { +enum class SnapshotType : unsigned char { + // Some action modifying project state. + Action, + // Selection change at the Plater. + Selection, + // New project, Reset project, Load project ... + ProjectSeparator, + // Entering a Gizmo, which opens a secondary Undo / Redo stack. + EnteringGizmo, + // Leaving a Gizmo, which closes a secondary Undo / Redo stack. + // No action modifying a project state was done between EnteringGizmo / LeavingGizmo. + LeavingGizmoNoAction, + // Leaving a Gizmo, which closes a secondary Undo / Redo stack. + // Some action modifying a project state was done between EnteringGizmo / LeavingGizmo. + LeavingGizmoWithAction, +}; + // Data structure to be stored with each snapshot. // Storing short data (bit masks, ints) with each snapshot instead of being serialized into the Undo / Redo stack // is likely cheaper in term of both the runtime and memory allocation. @@ -34,6 +51,7 @@ struct SnapshotData // Constructor is defined in .cpp due to the forward declaration of enum PrinterTechnology. SnapshotData(); + SnapshotType snapshot_type; PrinterTechnology printer_technology; // Bitmap of Flags (see the Flags enum). unsigned int flags; @@ -122,10 +140,13 @@ public: // There is one additional snapshot taken at the very end, which indicates the current unnamed state. const std::vector& snapshots() const; + const Snapshot& snapshot(size_t time) const; + // Timestamp of the active snapshot. One of the snapshots of this->snapshots() shall have Snapshot::timestamp equal to this->active_snapshot_time(). - // The snapshot time indicates start of an operation, which is finished at the time of the following snapshot, therefore - // the active snapshot is the successive snapshot. The same logic applies to the time_to_load parameter of undo() and redo() operations. + // The active snapshot may be a special placeholder "@@@ Topmost @@@" indicating an uncaptured current state, + // or the active snapshot may be an active state to which the application state was undoed or redoed. size_t active_snapshot_time() const; + const Snapshot& active_snapshot() const { return this->snapshot(this->active_snapshot_time()); } // Temporary snapshot is active if the topmost snapshot is active and it has not been captured yet. // In that case the Undo action will capture the last snapshot. bool temp_snapshot_active() const; From 3ee259b602947b10f1b225124c67c4b750a3c391 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 14:14:05 +0200 Subject: [PATCH 22/28] #7010 - Fixed import of volumes from 3mf. This is a regression wrt. PrusaSlicer 2.4.0-alpha1 due to the 3mf import optimization introduced with 8a2a9dba2f8f94da0106b60df613cd04ada4d595 --- src/libslic3r/Format/3mf.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 90fa9bfaed..895aa44137 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1890,6 +1890,7 @@ namespace Slic3r { unsigned int geo_tri_count = (unsigned int)geometry.triangles.size(); unsigned int renamed_volumes_count = 0; + int processed_vertices_max_id = 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) { @@ -1911,13 +1912,26 @@ namespace Slic3r { // splits volume out of imported geometry std::vector faces(geometry.triangles.begin() + volume_data.first_triangle_id, geometry.triangles.begin() + volume_data.last_triangle_id + 1); const size_t triangles_count = faces.size(); - for (Vec3i face : faces) - for (unsigned int tri_id : face) + + int min_id = faces.front()[0]; + int max_id = faces.front()[0]; + for (Vec3i& face : faces) { + for (int& tri_id : face) { if (tri_id < 0 || tri_id >= geometry.vertices.size()) { add_error("Found invalid vertex id"); return false; } - TriangleMesh triangle_mesh(std::move(geometry.vertices), std::move(faces)); + min_id = std::min(min_id, tri_id); + max_id = std::max(max_id, tri_id); + // rebase index to the current vertices list + tri_id -= processed_vertices_max_id; + } + } + + processed_vertices_max_id = 1 + std::max(processed_vertices_max_id, max_id); + + std::vector vertices(geometry.vertices.begin() + min_id, geometry.vertices.begin() + max_id + 1); + TriangleMesh triangle_mesh(std::move(vertices), std::move(faces)); if (m_version == 0) { // if the 3mf was not produced by PrusaSlicer and there is only one instance, From 9c4494637cff2fc7551dac9eae01d37b257d8eac Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 27 Sep 2021 14:32:09 +0200 Subject: [PATCH 23/28] WIP Undo / Redo and project state: Marking Undo / Redo snapshots with their purpose. Follow-up to 41dc265a45196fd6a8f2b79ac6e803f41cbe22f8 --- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 3 ++- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 474e316318..aa3d249c8b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -57,7 +57,8 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate) m_internal_stack_active = true; } if (!activate && m_internal_stack_active) { - bool project_modified = plater->leave_gizmos_stack(); + //FIXME report the true state! + bool project_modified = true; // plater->leave_gizmos_stack(); std::string str = get_painter_type() == PainterGizmoType::SEAM ? _u8L("Leaving Seam painting") : _u8L("Leaving Paint-on supports"); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 9a3bd5a426..835e69acb5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -926,9 +926,10 @@ void GLGizmoSlaSupports::on_set_state() } else { // we are actually shutting down - bool project_modified = disable_editing_mode(); // so it is not active next time the gizmo opens + //FIXME report the true state! + bool project_modified = true; // disable_editing_mode(); // so it is not active next time the gizmo opens Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Leaving SLA gizmo"), - project_modified ? UndoRedo::SnapshotType::LeavingGizmoWithAction : UndoRedo::SnapshotType::LeavingGizmoNo); + project_modified ? UndoRedo::SnapshotType::LeavingGizmoWithAction : UndoRedo::SnapshotType::LeavingGizmoNoAction); m_normal_cache.clear(); m_old_mo_id = -1; } From 85c760d9b68a361b9b20a665a09b4b3cf5d4ff69 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 27 Sep 2021 15:00:58 +0200 Subject: [PATCH 24/28] Touch-up to some comments, removed commented-out code --- src/libslic3r/Preset.cpp | 8 -------- src/libslic3r/PresetBundle.hpp | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f5c8235ed5..09cd384687 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1097,14 +1097,6 @@ size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfil return m_idx_selected; } -// Save the preset under a new name. If the name is different from the old one, -// a new preset is stored into the list of presets. -// All presets are marked as not modified and the new preset is activated. -//void PresetCollection::save_current_preset(const std::string &new_name); - -// Delete the current preset, activate the first visible preset. -//void PresetCollection::delete_current_preset(); - // Update a dirty flag of the current preset // Return true if the dirty flag changed. bool PresetCollection::update_dirty() diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index c22599e388..e5e49fb470 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -143,7 +143,7 @@ public: const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias) const; - // Save current preset of a required type under a new name. If the name is different from the old one, + // Save current preset of a provided type under a new name. If the name is different from the old one, // Unselected option would be reverted to the beginning values void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector& unselected_options); From 80f28538c5256722b59610850dd7145aa8c66ad4 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Sep 2021 16:03:09 +0200 Subject: [PATCH 25/28] #7011 - Follow-up of 3ee259b602947b10f1b225124c67c4b750a3c391 - Modified volumes' indices rebase --- src/libslic3r/Format/3mf.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 895aa44137..9f40159132 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1915,16 +1915,21 @@ namespace Slic3r { int min_id = faces.front()[0]; int max_id = faces.front()[0]; - for (Vec3i& face : faces) { - for (int& tri_id : face) { + for (const Vec3i& face : faces) { + for (const int tri_id : face) { if (tri_id < 0 || tri_id >= geometry.vertices.size()) { add_error("Found invalid vertex id"); return false; } min_id = std::min(min_id, tri_id); max_id = std::max(max_id, tri_id); - // rebase index to the current vertices list - tri_id -= processed_vertices_max_id; + } + } + + // rebase indices to the current vertices list + for (Vec3i& face : faces) { + for (int& tri_id : face) { + tri_id -= min_id; } } From 4e63f873da9637f3096ed4c894095884f3a9f219 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 29 Sep 2021 10:01:13 +0200 Subject: [PATCH 26/28] Slicing complete notification fades out after 2 seconds. Issue #7017. --- src/slic3r/GUI/NotificationManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 1b08e6cd25..98abb4863c 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1172,7 +1172,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std { NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slicing finished."), m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") }; update(data); - m_state = EState::NotFading; + m_state = EState::Shown; } break; default: @@ -1191,7 +1191,7 @@ void NotificationManager::SlicingProgressNotification::set_print_info(const std: void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(bool collapsed) { m_sidebar_collapsed = collapsed; - if (m_sp_state == SlicingProgressState::SP_COMPLETED) + if (m_sp_state == SlicingProgressState::SP_COMPLETED && collapsed) m_state = EState::NotFading; } @@ -1208,7 +1208,7 @@ int NotificationManager::SlicingProgressNotification::get_duration() if (m_sp_state == SlicingProgressState::SP_CANCELLED) return 2; else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed) - return 0; + return 2; else return 0; } From 5c1e6d2298d36db1ca2de2fc324419b2dacddeba Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 29 Sep 2021 10:11:29 +0200 Subject: [PATCH 27/28] Fix reading relative_correction parameter Drop compatibility with profiles created on legacy Slic3r PE 1.42-beta1 to 1.42-beta2 fixes #7013 --- src/libslic3r/SLAPrint.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 7899d173e1..004f7d5550 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1047,15 +1047,15 @@ Vec3d SLAPrint::relative_correction() const Vec3d corr(1., 1., 1.); if(printer_config().relative_correction.values.size() >= 2) { - corr(X) = printer_config().relative_correction.values[0]; - corr(Y) = printer_config().relative_correction.values[0]; - corr(Z) = printer_config().relative_correction.values.back(); + corr.x() = printer_config().relative_correction.values[0]; + corr.y() = corr.x(); + corr.z() = printer_config().relative_correction.values[1]; } if(material_config().material_correction.values.size() >= 2) { - corr(X) *= material_config().material_correction.values[0]; - corr(Y) *= material_config().material_correction.values[0]; - corr(Z) *= material_config().material_correction.values.back(); + corr.x() *= material_config().material_correction.values[0]; + corr.y() = corr.x(); + corr.z() *= material_config().material_correction.values[1]; } return corr; From 1df91ea93008eacc43b24a6b763bea482b2ae81b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 29 Sep 2021 13:34:30 +0200 Subject: [PATCH 28/28] Follow-up of 67e519d3ab8f56d9ab5d6759d1b92ee9131ead8c - Use a platform-indipendent fix --- src/slic3r/GUI/GCodeViewer.cpp | 126 +++++++++++++++++++++++---------- src/slic3r/GUI/GCodeViewer.hpp | 4 ++ src/slic3r/GUI/GLCanvas3D.cpp | 5 ++ src/slic3r/GUI/GLCanvas3D.hpp | 3 + src/slic3r/GUI/Plater.cpp | 4 +- 5 files changed, 100 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index e8a7379577..4a3849af81 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -573,6 +573,89 @@ GCodeViewer::GCodeViewer() // m_sequential_view.skip_invisible_moves = true; } +#if ENABLE_SEAMS_USING_MODELS +void GCodeViewer::init() +{ + if (m_gl_data_initialized) + return; + + // initializes opengl data of TBuffers + for (size_t i = 0; i < m_buffers.size(); ++i) { + TBuffer& buffer = m_buffers[i]; + EMoveType type = buffer_type(i); + switch (type) + { + default: { break; } + case EMoveType::Tool_change: + case EMoveType::Color_change: + case EMoveType::Pause_Print: + case EMoveType::Custom_GCode: + case EMoveType::Retract: + case EMoveType::Unretract: + case EMoveType::Seam: { +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; + buffer.shader = "gouraud_light_instanced"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; + } + else { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; + buffer.shader = "gouraud_light"; + + buffer.model.data = diamond(16); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; + } + break; +#else + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; + buffer.shader = "gouraud_light_instanced"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + } + else { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; + buffer.vertices.format = VBuffer::EFormat::Position; + buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; + } + break; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS + } + case EMoveType::Wipe: + case EMoveType::Extrude: { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; + buffer.shader = "gouraud_light"; + break; + } + case EMoveType::Travel: { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; + buffer.vertices.format = VBuffer::EFormat::PositionNormal1; + buffer.shader = "toolpaths_lines"; + break; + } + } + + set_toolpath_move_type_visible(EMoveType::Extrude, true); + } + + // initializes tool marker + m_sequential_view.marker.init(); + + // initializes point sizes + std::array point_sizes; + ::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data()); + m_detected_point_sizes = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; + + m_gl_data_initialized = true; +} +#endif // ENABLE_SEAMS_USING_MODELS + void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized) { // avoid processing if called with the same gcode_result @@ -756,6 +839,7 @@ void GCodeViewer::reset() void GCodeViewer::render() { +#if !ENABLE_SEAMS_USING_MODELS auto init_gl_data = [this]() { // initializes opengl data of TBuffers for (size_t i = 0; i < m_buffers.size(); ++i) { @@ -771,26 +855,6 @@ void GCodeViewer::render() case EMoveType::Retract: case EMoveType::Unretract: case EMoveType::Seam: { -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; - buffer.shader = "gouraud_light_instanced"; - buffer.model.model.init_from(diamond(16)); - buffer.model.color = option_color(type); - buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; - } - else { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; - buffer.vertices.format = VBuffer::EFormat::PositionNormal3; - buffer.shader = "gouraud_light"; - - buffer.model.data = diamond(16); - buffer.model.color = option_color(type); - buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; - } - break; -#else if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; buffer.shader = "gouraud_light_instanced"; @@ -803,36 +867,17 @@ void GCodeViewer::render() buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; } break; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#else - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; - buffer.vertices.format = VBuffer::EFormat::Position; - buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; - break; -#endif // ENABLE_SEAMS_USING_MODELS } case EMoveType::Wipe: case EMoveType::Extrude: { -#if ENABLE_SEAMS_USING_MODELS - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; - buffer.vertices.format = VBuffer::EFormat::PositionNormal3; -#endif // ENABLE_SEAMS_USING_MODELS buffer.shader = "gouraud_light"; break; } case EMoveType::Travel: { -#if ENABLE_SEAMS_USING_MODELS - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; - buffer.vertices.format = VBuffer::EFormat::PositionNormal1; -#endif // ENABLE_SEAMS_USING_MODELS buffer.shader = "toolpaths_lines"; break; } } - -#if ENABLE_SEAMS_USING_MODELS - set_toolpath_move_type_visible(EMoveType::Extrude, true); -#endif // ENABLE_SEAMS_USING_MODELS } // initializes tool marker @@ -844,6 +889,7 @@ void GCodeViewer::render() m_detected_point_sizes = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; m_gl_data_initialized = true; }; +#endif // !ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_opengl(); @@ -852,10 +898,12 @@ void GCodeViewer::render() #endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS +#if !ENABLE_SEAMS_USING_MODELS // OpenGL data must be initialized after the glContext has been created. // This is ensured when this method is called by GLCanvas3D::_render_gcode(). if (!m_gl_data_initialized) init_gl_data(); +#endif // !ENABLE_SEAMS_USING_MODELS if (m_roles.empty()) return; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 6c164f5e8f..1b5a53f9d7 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -808,6 +808,10 @@ public: GCodeViewer(); ~GCodeViewer() { reset(); } +#if ENABLE_SEAMS_USING_MODELS + void init(); +#endif // ENABLE_SEAMS_USING_MODELS + // extract rendering data from the given parameters void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized); // recalculate ranges in dependence of what is visible and sets tool/print colors diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5953c56608..869f48a01f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1400,6 +1400,11 @@ void GLCanvas3D::render() if (!is_initialized() && !init()) return; +#if ENABLE_SEAMS_USING_MODELS + if (!m_main_toolbar.is_enabled()) + m_gcode_viewer.init(); +#endif // ENABLE_SEAMS_USING_MODELS + if (wxGetApp().plater()->get_bed().get_shape().empty()) { // this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE post_event(SimpleEvent(EVT_GLCANVAS_UPDATE_BED_SHAPE)); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e03c4a71db..86ec5634fe 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -617,6 +617,9 @@ public: void reset_volumes(); ModelInstanceEPrintVolumeState check_volumes_outside_state() const; +#if ENABLE_SEAMS_USING_MODELS + void init_gcode_viewer() { m_gcode_viewer.init(); } +#endif // ENABLE_SEAMS_USING_MODELS void reset_gcode_toolpaths() { m_gcode_viewer.reset(); } const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6cef0933a7..87b83ec24b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3801,9 +3801,7 @@ void Plater::priv::set_current_panel(wxPanel* panel) bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside; if (!model.objects.empty() && !export_in_progress && model_fits) { #if ENABLE_SEAMS_USING_MODELS - // the following call is needed to ensure that GCodeViewer buffers are initialized - // before calling reslice() when background processing is active - preview->SetFocusFromKbd(); + preview->get_canvas3d()->init_gcode_viewer(); #endif // ENABLE_SEAMS_USING_MODELS q->reslice(); }