From b0dd328fdec094cd072ece2cbfff87dcf07d51c2 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 20 Aug 2018 11:27:25 +0200 Subject: [PATCH] Lay flat - icons and invalidation improvement --- lib/Slic3r/GUI/Plater.pm | 2 +- resources/icons/overlay/layflat_hover.png | Bin 0 -> 2410 bytes resources/icons/overlay/layflat_off.png | Bin 0 -> 2864 bytes resources/icons/overlay/layflat_on.png | Bin 0 -> 3816 bytes xs/src/libslic3r/TriangleMesh.cpp | 5 +++++ xs/src/libslic3r/TriangleMesh.hpp | 1 + xs/src/slic3r/GUI/GLGizmo.cpp | 23 ++++++++++++++-------- xs/src/slic3r/GUI/GLGizmo.hpp | 1 + 8 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 resources/icons/overlay/layflat_hover.png create mode 100644 resources/icons/overlay/layflat_off.png create mode 100644 resources/icons/overlay/layflat_on.png diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 8ab749e24..98f31fb8b 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -143,7 +143,7 @@ sub new { my $on_gizmo_rotate = sub { my ($angle_z, $angle_y) = @_; $self->rotate(rad2deg($angle_z), Z, 'absolute'); - $self->rotate(rad2deg($angle_y), Y, 'absolute'); + $self->rotate(rad2deg($angle_y), Y, 'absolute') if $angle_y != 0; }; # callback to update object's geometry info while using gizmos diff --git a/resources/icons/overlay/layflat_hover.png b/resources/icons/overlay/layflat_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..afce81d19ee2a26916a1e7684f1bef13e42e486c GIT binary patch literal 2410 zcmV-w36=JVP)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00002 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 literal 0 HcmV?d00001 diff --git a/resources/icons/overlay/layflat_off.png b/resources/icons/overlay/layflat_off.png new file mode 100644 index 0000000000000000000000000000000000000000..70d198112910a86d34a96bd7e536bfd79a75ae5c GIT binary patch literal 2864 zcmV-03(xe4P)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00002 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[0].x : nullptr; +} + void TriangleMesh::require_shared_vertices() { diff --git a/xs/src/libslic3r/TriangleMesh.hpp b/xs/src/libslic3r/TriangleMesh.hpp index 6ab52efe2..be151f062 100644 --- a/xs/src/libslic3r/TriangleMesh.hpp +++ b/xs/src/libslic3r/TriangleMesh.hpp @@ -53,6 +53,7 @@ public: TriangleMeshPtrs split() const; void merge(const TriangleMesh &mesh); ExPolygons horizontal_projection() const; + const float* first_vertex() const; Polygon convex_hull(); BoundingBoxf3 bounding_box() const; // Returns the bbox of this TriangleMesh transformed by the given matrix diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index f0a8f2e71..2b91afe41 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -515,15 +515,15 @@ bool GLGizmoFlatten::on_init() { std::string path = resources_dir() + "/icons/overlay/"; - std::string filename = path + "scale_off.png"; + std::string filename = path + "layflat_off.png"; if (!m_textures[Off].load_from_file(filename, false)) return false; - filename = path + "scale_hover.png"; + filename = path + "layflat_hover.png"; if (!m_textures[Hover].load_from_file(filename, false)) return false; - filename = path + "scale_on.png"; + filename = path + "layflat_on.png"; if (!m_textures[On].load_from_file(filename, false)) return false; @@ -591,12 +591,12 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const // TODO - remove and use Eigen instead -static Pointf3 super_rotation(const Pointf3& axis, float angle, const Pointf3& point) +static Pointf3 super_rotation(Pointf3 axis, float angle, const Pointf3& point) { - float axis_length = axis.distance_to(Pointf3(0.f, 0.f, 0.f)); - float x = axis.x / axis_length; - float y = axis.y / axis_length; - float z = axis.z / axis_length; + axis = normalize(axis); + const float& x = axis.x; + const float& y = axis.y; + const float& z = axis.z; float s = sin(angle); float c = cos(angle); float D = 1-c; @@ -774,6 +774,8 @@ void GLGizmoFlatten::update_planes() m_source_data.bounding_boxes.push_back(vol->get_convex_hull().bounding_box()); m_source_data.scaling_factor = m_model_object->instances.front()->scaling_factor; m_source_data.rotation = m_model_object->instances.front()->rotation; + const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex(); + m_source_data.mesh_first_point = Pointf3(first_vertex[0], first_vertex[1], first_vertex[3]); } // Check if the bounding boxes of each volume's convex hull is the same as before @@ -793,6 +795,11 @@ bool GLGizmoFlatten::is_plane_update_necessary() const if (m_model_object->volumes[i]->get_convex_hull().bounding_box() != m_source_data.bounding_boxes[i]) return true; + const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex(); + Pointf3 first_point(first_vertex[0], first_vertex[1], first_vertex[2]); + if (first_point != m_source_data.mesh_first_point) + return true; + return false; } diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 0cab603eb..2c82f73f3 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -166,6 +166,7 @@ private: std::vector bounding_boxes; // bounding boxes of convex hulls of individual volumes float scaling_factor; float rotation; + Pointf3 mesh_first_point; }; // This holds information to decide whether recalculation is necessary: