diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index e9b13b23d..bc78e6b7f 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -79,7 +79,9 @@ public: // Only if the user really modified the layer height, layer_height_profile_valid is set // and used subsequently by the PrintObject. bool layer_height_profile_valid; - + + // This vector holds position of selected support points for SLA. The data are + // saved in mesh coordinates to allow using them for several instances. std::vector sla_support_points; /* This vector accumulates the total translation applied to the object by the diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 6859f37fa..5b9f4da89 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -13,8 +13,6 @@ #include "../../libslic3r/GCode/PreviewData.hpp" #include -#include -#include #include #include @@ -48,6 +46,8 @@ static const float VIEW_REAR[2] = { 180.0f, 90.0f }; static const float VARIABLE_LAYER_THICKNESS_BAR_WIDTH = 70.0f; static const float VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT = 22.0f; +static const float GIZMO_RESET_BUTTON_HEIGHT = 22.0f; +static const float GIZMO_RESET_BUTTON_WIDTH = 70.f; static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, @@ -1350,14 +1350,14 @@ bool GLCanvas3D::Gizmos::grabber_contains_mouse() const return (curr != nullptr) ? (curr->get_hover_id() != -1) : false; } -void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray) +void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, const Point* mouse_pos) { if (!m_enabled) return; GLGizmoBase* curr = _get_current(); if (curr != nullptr) - curr->update(mouse_ray); + curr->update(mouse_ray, mouse_pos); } GLCanvas3D::Gizmos::EType GLCanvas3D::Gizmos::get_current_type() const @@ -1480,14 +1480,24 @@ void GLCanvas3D::Gizmos::set_model_object_ptr(const ModelObject* model_object) reinterpret_cast(it->second)->set_model_object_ptr(model_object); } -void GLCanvas3D::Gizmos::move_current_point(const Vec2d& mouse_position) +void GLCanvas3D::Gizmos::clicked_on_object(const Vec2d& mouse_position) { if (!m_enabled) return; GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); if (it != m_gizmos.end()) - reinterpret_cast(it->second)->move_current_point(mouse_position); + reinterpret_cast(it->second)->clicked_on_object(mouse_position); +} + +void GLCanvas3D::Gizmos::delete_current_grabber(bool delete_all) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->delete_current_grabber(delete_all); } void GLCanvas3D::Gizmos::render_current_gizmo(const BoundingBoxf3& box) const @@ -2433,6 +2443,26 @@ void GLCanvas3D::update_gizmos_data() } } +// Returns a Rect object denoting size and position of the Reset button used by a gizmo. +// Returns in either screen or viewport coords. +Rect GLCanvas3D::get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const +{ + const Size& cnv_size = canvas.get_canvas_size(); + float w = (viewport ? -0.5f : 0.f) * (float)cnv_size.get_width(); + float h = (viewport ? 0.5f : 1.f) * (float)cnv_size.get_height(); + float zoom = canvas.get_camera_zoom(); + float inv_zoom = viewport ? ((zoom != 0.0f) ? 1.0f / zoom : 0.0f) : 1.f; + const float gap = 30.f; + return Rect((w + gap + 80.f) * inv_zoom, (viewport ? -1.f : 1.f) * (h - GIZMO_RESET_BUTTON_HEIGHT) * inv_zoom, + (w + gap + 80.f + GIZMO_RESET_BUTTON_WIDTH) * inv_zoom, (viewport ? -1.f : 1.f) * (h * inv_zoom)); +} + +bool GLCanvas3D::gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const +{ + const Rect& rect = get_gizmo_reset_rect(canvas, false); + return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); +} + void GLCanvas3D::render() { if (m_canvas == nullptr) @@ -3103,13 +3133,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } } + else if ((m_gizmos.get_current_type() == Gizmos::SlaSupports) && gizmo_reset_rect_contains(*this, pos(0), pos(1))) + { + if (evt.LeftDown()) + { + m_gizmos.delete_current_grabber(true); + m_wait_for_left_up = true; + m_dirty = true; + } + } else if ((selected_object_idx != -1) && gizmos_overlay_contains_mouse) { update_gizmos_data(); m_gizmos.update_on_off_state(*this, m_mouse.position); m_dirty = true; } - else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) + else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse() && evt.LeftDown()) { update_gizmos_data(); m_gizmos.start_dragging(_selected_volumes_bounding_box()); @@ -3127,6 +3166,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } + else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse() && evt.RightDown()) { + if (m_gizmos.get_current_type() == Gizmos::SlaSupports) + m_gizmos.delete_current_grabber(); + } else if (toolbar_contains_mouse != -1) { m_toolbar_action_running = true; @@ -3169,7 +3212,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { // The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate pos x, y, // an converts the screen space coordinate to unscaled object space. - Vec3d pos3d = (volume_idx == -1) ? Vec3d(DBL_MAX, DBL_MAX, DBL_MAX) : _mouse_to_3d(pos); // Only accept the initial position, if it is inside the volume bounding box. @@ -3260,7 +3302,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_canvas->CaptureMouse(); m_mouse.dragging = true; - m_gizmos.update(mouse_ray(pos)); + m_gizmos.update(mouse_ray(pos), &pos); std::vector volumes; if (m_mouse.drag.gizmo_volume_idx != -1) @@ -3315,11 +3357,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) update_rotation_value((double)angle_z, Z); break; } - case Gizmos::SlaSupports: - { - m_gizmos.move_current_point(Vec2d(pos(0), pos(1))); - break; - } default: break; } @@ -3382,6 +3419,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) { + if (evt.LeftUp() && m_wait_for_left_up) + m_wait_for_left_up = false; + else if (m_layers_editing.state != LayersEditing::Unknown) { m_layers_editing.state = LayersEditing::Unknown; @@ -3417,38 +3457,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { int id = _get_first_selected_object_id(); if ((id != -1) && (m_model != nullptr)) { - ModelObject* model_object = m_model->objects[id]; - const stl_file& stl = model_object->mesh().stl; - Eigen::MatrixXf V; // vertices - Eigen::MatrixXi F;// facets indices - V.resize(3*stl.stats.number_of_facets, 3); - F.resize(stl.stats.number_of_facets, 3); - for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); - V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); - V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); - F(i, 0) = 3*i+0; - F(i, 1) = 3*i+1; - F(i, 2) = 3*i+2; - } - - Eigen::Matrix viewport; - ::glGetIntegerv(GL_VIEWPORT, viewport.data()); - Eigen::Matrix modelview_matrix; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); - Eigen::Matrix projection_matrix; - ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); - - int fid = 0; - Vec3f bc(0, 0, 0); - if (igl::unproject_onto_mesh(Vec2f(pos(0), viewport(3)-pos(1)), modelview_matrix.cast(), projection_matrix.cast(), viewport.cast(), V, F, fid, bc) - && (stl.facet_start + fid)->normal(2) < 0.f) { - const Vec3f& a = (stl.facet_start+fid)->vertex[0]; - const Vec3f& b = (stl.facet_start+fid)->vertex[1]; - const Vec3f& c = (stl.facet_start+fid)->vertex[2]; - model_object->sla_support_points.emplace_back(bc(0)*a + bc(1)*b + bc(2)*c); - } + m_gizmos.clicked_on_object(Vec2d(pos(0), pos(1))); } } else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled()) @@ -4184,61 +4193,6 @@ void GLCanvas3D::_render_legend_texture() const m_legend_texture.render(*this); } - - - - -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -void GLCanvas3D::_render_sla_support_points() const -{ - if (m_print == nullptr) - return; - - GLVolume* volume = nullptr; - - for (GLVolume* vol : m_volumes.volumes) { - if ((vol != nullptr) && vol->selected) { - volume = vol; - break; - } - } - - if (volume == nullptr) - return; - - // If the active object was not allocated at the Print, go away.This should only be a momentary case between an object addition / deletion - // and an update by Platter::async_apply_config. - int object_idx = int(volume->select_group_id / 1000000); - if ((int)m_print->objects.size() < object_idx) - return; - - const PrintObject* print_object = m_print->get_object(object_idx); - if (print_object == nullptr) - return; - - const ModelObject* model_object = print_object->model_object(); - if (!model_object->instances.empty()) { - for (const auto& point : model_object->sla_support_points) { - ::glColor4f(0.9f, 0.f, 0.f, 0.75f); - ::glPushMatrix(); - ::glTranslatef(point(0), point(1), point(2)); - GLUquadricObj *quadric; - quadric = ::gluNewQuadric(); - - ::gluQuadricDrawStyle(quadric, GLU_FILL ); - ::gluSphere( quadric , 0.5 , 36 , 18 ); - ::gluDeleteQuadric(quadric); - ::glPopMatrix(); - } - } -} -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - - - - - - void GLCanvas3D::_render_layer_editing_overlay() const { if (m_print == nullptr) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index d19622945..07c12a9a6 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -366,8 +366,9 @@ class GLCanvas3D bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool grabber_contains_mouse() const; - void update(const Linef3& mouse_ray); + void update(const Linef3& mouse_ray, const Point* mouse_pos = nullptr); + Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const; EType get_current_type() const; bool is_running() const; @@ -389,7 +390,8 @@ class GLCanvas3D Vec3d get_flattening_normal() const; void set_model_object_ptr(const ModelObject* model_object); - void move_current_point(const Vec2d& mouse_position); + void clicked_on_object(const Vec2d& mouse_position); + void delete_current_grabber(bool delete_all = false); void render_current_gizmo(const BoundingBoxf3& box) const; @@ -478,6 +480,7 @@ class GLCanvas3D bool m_shader_enabled; bool m_dynamic_background_enabled; bool m_multisample_allowed; + bool m_wait_for_left_up; std::string m_color_by; std::string m_select_by; @@ -597,6 +600,8 @@ public: void update_volumes_colors_by_extruder(); void update_gizmos_data(); + Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const; + bool gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const; void render(); diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index cdd0f29ee..3fca62667 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -153,6 +153,7 @@ void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_ ::glRotatef((GLfloat)angles(1) * rad_to_deg, 0.0f, 1.0f, 0.0f); ::glRotatef((GLfloat)angles(2) * rad_to_deg, 0.0f, 0.0f, 1.0f); + // face min x ::glPushMatrix(); ::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f); @@ -281,10 +282,10 @@ void GLGizmoBase::stop_dragging() on_stop_dragging(); } -void GLGizmoBase::update(const Linef3& mouse_ray) +void GLGizmoBase::update(const Linef3& mouse_ray, const Point* mouse_pos) { if (m_hover_id != -1) - on_update(mouse_ray); + on_update(mouse_ray, mouse_pos); } float GLGizmoBase::picking_color_component(unsigned int id) const @@ -371,7 +372,7 @@ void GLGizmoRotate::on_start_dragging(const BoundingBoxf3& box) m_radius = Offset + box.radius(); } -void GLGizmoRotate::on_update(const Linef3& mouse_ray) +void GLGizmoRotate::on_update(const Linef3& mouse_ray, const Point* mouse_position) { Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(mouse_ray)); @@ -694,7 +695,6 @@ void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const } const float GLGizmoScale3D::Offset = 5.0f; -const Vec3d GLGizmoScale3D::OffsetVec = (double)GLGizmoScale3D::Offset * Vec3d::Ones(); GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent) : GLGizmoBase(parent) @@ -744,11 +744,11 @@ void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box) { m_starting_drag_position = m_grabbers[m_hover_id].center; m_show_starting_box = true; - m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); + m_starting_box = box; } } -void GLGizmoScale3D::on_update(const Linef3& mouse_ray) +void GLGizmoScale3D::on_update(const Linef3& mouse_ray, const Point* mouse_pos) { if ((m_hover_id == 0) || (m_hover_id == 1)) do_scale_x(mouse_ray); @@ -778,7 +778,9 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glEnable(GL_DEPTH_TEST); - m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); + Vec3d offset_vec = (double)Offset * Vec3d::Ones(); + + m_box = BoundingBoxf3(box.min - offset_vec, box.max + offset_vec); const Vec3d& center = m_box.center(); // x axis @@ -1072,7 +1074,7 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) } } -void GLGizmoMove3D::on_update(const Linef3& mouse_ray) +void GLGizmoMove3D::on_update(const Linef3& mouse_ray, const Point* mouse_pos) { if (m_hover_id == 0) m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0); @@ -1527,77 +1529,92 @@ bool GLGizmoSlaSupports::on_init() return true; } - - -void GLGizmoSlaSupports::on_start_dragging() -{ - if (m_hover_id != -1) - ;//m_normal = m_planes[m_hover_id].normal; -} - void GLGizmoSlaSupports::on_render(const BoundingBoxf3& box) const { ::glEnable(GL_BLEND); ::glEnable(GL_DEPTH_TEST); - if (m_model_object && !m_model_object->instances.empty()) { - for (int i=0; i<(int)m_model_object->sla_support_points.size(); ++i) { - const auto& point = m_model_object->sla_support_points[i]; - if (i == m_hover_id) - ::glColor4f(0.9f, 0.f, 0.f, 0.75f); - else - ::glColor4f(0.5f, 0.f, 0.f, 0.75f); - - ::glPushMatrix(); - ::glTranslatef(point(0), point(1), point(2)); - GLUquadricObj *quadric; - quadric = ::gluNewQuadric(); - ::gluQuadricDrawStyle(quadric, GLU_FILL ); - ::gluSphere( quadric , 0.5 , 36 , 18 ); - ::gluDeleteQuadric(quadric); - ::glPopMatrix(); - } + for (auto& g : m_grabbers) { + g.color[0] = 1.f; + g.color[1] = 0.f; + g.color[2] = 0.f; } + render_grabbers(); + render_tooltip_texture(); + ::glDisable(GL_BLEND); } void GLGizmoSlaSupports::on_render_for_picking(const BoundingBoxf3& box) const { ::glEnable(GL_DEPTH_TEST); + for (unsigned int i=0; iinstances.empty()) { - for (unsigned int i=0; isla_support_points.size(); ++i) { - const auto& point = m_model_object->sla_support_points[i]; - ::glColor3f(1.0f, 1.0f, picking_color_component(i)); - ::glPushMatrix(); - ::glTranslatef(point(0), point(1), point(2)); - GLUquadricObj *quadric; - quadric = ::gluNewQuadric(); +void GLGizmoSlaSupports::render_grabbers(bool picking) const +{ + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + if (!m_grabbers[i].enabled) + continue; - ::gluQuadricDrawStyle(quadric, GLU_FILL ); - ::gluSphere( quadric , 0.5 , 36 , 18 ); - ::gluDeleteQuadric(quadric); - ::glPopMatrix(); + float render_color[3]; + if (!picking && m_hover_id == i) { + render_color[0] = 1.0f - m_grabbers[i].color[0]; + render_color[1] = 1.0f - m_grabbers[i].color[1]; + render_color[2] = 1.0f - m_grabbers[i].color[2]; } + else + ::memcpy((void*)render_color, (const void*)m_grabbers[i].color, 3 * sizeof(float)); + if (!picking) + ::glEnable(GL_LIGHTING); + ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); + ::glPushMatrix(); + const Vec3d& center = m_grabbers[i].center; + ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); + GLUquadricObj *quadric; + quadric = ::gluNewQuadric(); + ::gluQuadricDrawStyle(quadric, GLU_FILL ); + ::gluSphere( quadric , 0.5f, 36 , 18 ); + ::gluDeleteQuadric(quadric); + ::glPopMatrix(); + if (!picking) + ::glDisable(GL_LIGHTING); } } -void GLGizmoSlaSupports::move_current_point(const Vec2d& mouse_position) +Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) { - const stl_file& stl = m_model_object->mesh().stl; - Eigen::MatrixXf V; // vertices - Eigen::MatrixXi F;// facets indices - V.resize(3*stl.stats.number_of_facets, 3); - F.resize(stl.stats.number_of_facets, 3); - for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); - V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); - V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); - F(i, 0) = 3*i+0; - F(i, 1) = 3*i+1; - F(i, 2) = 3*i+2; + // if the gizmo doesn't have the V, F structures for igl, calculate them first: + if (m_V.size() == 0) { + Eigen::MatrixXf& V = m_V; + Eigen::MatrixXi& F = m_F; + + TriangleMesh combined_mesh; + for (const ModelVolume* vol : m_model_object->volumes) + combined_mesh.merge(vol->mesh); + //combined_mesh.scale(m_model_object->instances.front()->scaling_factor); + //combined_mesh.rotate_z(m_model_object->instances.front()->rotation); + //const stl_file& stl = combined_mesh.stl; + const stl_file& stl = m_model_object->mesh().stl; + + V.resize(3*stl.stats.number_of_facets, 3); + F.resize(stl.stats.number_of_facets, 3); + for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); + V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); + V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); + F(i, 0) = 3*i+0; + F(i, 1) = 3*i+1; + F(i, 2) = 3*i+2; + } } Eigen::Matrix viewport; @@ -1608,19 +1625,89 @@ void GLGizmoSlaSupports::move_current_point(const Vec2d& mouse_position) ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); int fid = 0; - Vec3f bc(0, 0, 0); - Vec3f final_pos; - if (igl::unproject_onto_mesh(Vec2f(mouse_position(0), viewport(3)-mouse_position(1)), modelview_matrix.cast(), projection_matrix.cast(), viewport.cast(), V, F, fid, bc) - && (stl.facet_start + fid)->normal(2) < 0.f) { - const Vec3f& a = (stl.facet_start+fid)->vertex[0]; - const Vec3f& b = (stl.facet_start+fid)->vertex[1]; - const Vec3f& c = (stl.facet_start+fid)->vertex[2]; - final_pos = bc(0)*a + bc(1)*b + bc(2)*c; - const_cast(m_model_object)->sla_support_points[m_hover_id] = final_pos; + Eigen::Vector3f bc(0, 0, 0); + if (!igl::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), modelview_matrix.cast(), projection_matrix.cast(), viewport.cast(), m_V, m_F, fid, bc)) + /*if (!igl::embree::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), + m_F, + modelview_matrix.cast(), + projection_matrix.cast(), + viewport.cast(), + m_intersector, + fid, + bc))*/ + throw "unable to unproject_onto_mesh"; + + const Vec3f& a = m_V.row(m_F(fid, 0)); + const Vec3f& b = m_V.row(m_F(fid, 1)); + const Vec3f& c = m_V.row(m_F(fid, 2)); + return bc(0)*a + bc(1)*b + bc(2)*c; +} + +void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position) +{ + Vec3f new_pos; + try { + new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new grabber in that case + m_grabbers.push_back(Grabber()); + m_grabbers.back().center = new_pos.cast(); + } + catch (...) {} +} + +void GLGizmoSlaSupports::delete_current_grabber(bool delete_all) +{ + if (delete_all) { + m_grabbers.clear(); + } + else + if (m_hover_id != -1) { + m_grabbers.erase(m_grabbers.begin() + m_hover_id); + m_hover_id = -1; + } +} + +void GLGizmoSlaSupports::on_update(const Linef3& mouse_ray, const Point* mouse_pos) +{ + if (m_hover_id != -1 && mouse_pos) { + Vec3f new_pos; + try { + new_pos = unproject_on_mesh(Vec2d((*mouse_pos)(0), (*mouse_pos)(1))); + m_grabbers[m_hover_id].center = new_pos.cast(); + } + catch (...) {} } } +void GLGizmoSlaSupports::render_tooltip_texture() const { + if (m_tooltip_texture.get_id() == 0) + if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_tooltip.png", false)) + return; + if (m_reset_texture.get_id() == 0) + if (!m_reset_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_reset.png", false)) + return; + + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float gap = 30.0f * inv_zoom; + + const Size& cnv_size = m_parent.get_canvas_size(); + float l = gap - cnv_size.get_width()/2.f * inv_zoom; + float r = l + (float)m_tooltip_texture.get_width() * inv_zoom; + float b = gap - cnv_size.get_height()/2.f * inv_zoom; + float t = b + (float)m_tooltip_texture.get_height() * inv_zoom; + + Rect reset_rect = m_parent.get_gizmo_reset_rect(m_parent, true); + + ::glDisable(GL_DEPTH_TEST); + ::glPushMatrix(); + ::glLoadIdentity(); + GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t); + GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); + ::glPopMatrix(); + ::glEnable(GL_DEPTH_TEST); +} + } // namespace GUI } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 3ee1b743f..fb02b7aa7 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -92,7 +92,7 @@ public: void stop_dragging(); bool is_dragging() const { return m_dragging; } - void update(const Linef3& mouse_ray); + void update(const Linef3& mouse_ray, const Point* mouse_pos); void render(const BoundingBoxf3& box) const { on_render(box); } void render_for_picking(const BoundingBoxf3& box) const { on_render_for_picking(box); } @@ -105,7 +105,7 @@ protected: virtual void on_disable_grabber(unsigned int id) {} virtual void on_start_dragging(const BoundingBoxf3& box) {} virtual void on_stop_dragging() {} - virtual void on_update(const Linef3& mouse_ray) = 0; + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos) = 0; virtual void on_render(const BoundingBoxf3& box) const = 0; virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; @@ -154,7 +154,7 @@ public: protected: virtual bool on_init(); virtual void on_start_dragging(const BoundingBoxf3& box); - virtual void on_update(const Linef3& mouse_ray); + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos); virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; @@ -215,11 +215,11 @@ protected: } virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_stop_dragging(); - virtual void on_update(const Linef3& mouse_ray) + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos) { for (GLGizmoRotate& g : m_gizmos) { - g.update(mouse_ray); + g.update(mouse_ray, mouse_pos); } } virtual void on_render(const BoundingBoxf3& box) const; @@ -264,7 +264,7 @@ protected: virtual bool on_init(); virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_stop_dragging() { m_show_starting_box = false; } - virtual void on_update(const Linef3& mouse_ray); + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos); virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; @@ -298,7 +298,7 @@ public: protected: virtual bool on_init(); virtual void on_start_dragging(const BoundingBoxf3& box); - virtual void on_update(const Linef3& mouse_ray); + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos); virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; @@ -349,7 +349,7 @@ public: protected: virtual bool on_init(); virtual void on_start_dragging(const BoundingBoxf3& box); - virtual void on_update(const Linef3& mouse_ray) {} + virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos) {} virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; virtual void on_set_state() @@ -361,21 +361,29 @@ protected: class GLGizmoSlaSupports : public GLGizmoBase { -// This gizmo does not use grabbers. The m_hover_id relates to shape managed by the class itself. private: const ModelObject* m_model_object = nullptr; + Vec3f unproject_on_mesh(const Vec2d& mouse_pos); + + Eigen::MatrixXf m_V; // vertices + Eigen::MatrixXi m_F; // facets indices public: explicit GLGizmoSlaSupports(GLCanvas3D& parent); void set_model_object_ptr(const ModelObject* model_object) { m_model_object = model_object; } - void move_current_point(const Vec2d& mouse_position); + void clicked_on_object(const Vec2d& mouse_position); + void delete_current_grabber(bool delete_all); -protected: - virtual bool on_init(); - virtual void on_start_dragging(); - virtual void on_update(const Linef3& mouse_ray) {} - virtual void on_render(const BoundingBoxf3& box) const; - virtual void on_render_for_picking(const BoundingBoxf3& box) const; +private: + bool on_init(); + void on_update(const Linef3& mouse_ray, const Point* mouse_pos); + void on_render(const BoundingBoxf3& box) const; + void on_render_for_picking(const BoundingBoxf3& box) const; + void render_grabbers(bool picking = false) const; + void render_tooltip_texture() const; + + mutable GLTexture m_tooltip_texture; + mutable GLTexture m_reset_texture; }; } // namespace GUI