diff --git a/resources/icons/cut_.svg b/resources/icons/cut_.svg new file mode 100644 index 0000000000..a7f462bb9c --- /dev/null +++ b/resources/icons/cut_.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 5e018a2129..dcb4c503a7 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1474,8 +1474,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const } } } - else if (!volume->mesh().empty() && - !volume->source.is_connector // we don't allow to cut a connectors + else if (!volume->mesh().empty() +// && !volume->source.is_connector // we don't allow to cut a connectors ) { // Transform the mesh by the combined transformation matrix. // Flip the triangles in case the composite transformation is left handed. diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index dbaded841c..c0b2e8e39f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -231,8 +231,8 @@ struct CutConnector : pos(Vec3d::Zero()), rotation(Vec3d::UnitZ()), radius(5.f), height(10.f) {} - CutConnector(Vec3d p, Vec3d n, float r, float h, bool fl = false) - : pos(p), rotation(n), radius(r), height(h), failed(fl) + CutConnector(Vec3d p, Vec3d rot, float r, float h, bool fl = false) + : pos(p), rotation(rot), radius(r), height(h), failed(fl) {} CutConnector(const CutConnector& rhs) : diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 5448dd1a2d..ea82d61e29 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -30,9 +30,7 @@ GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, , m_connector_style (size_t(CutConnectorStyle::Prizm)) , m_connector_shape_id (size_t(CutConnectorShape::Hexagon)) , m_rotation_gizmo(GLGizmoRotate3D(parent, "", -1)) - , m_rotation_matrix( Eigen::AngleAxisd(0.0, Vec3d::UnitZ()) - * Eigen::AngleAxisd(0.0, Vec3d::UnitY()) - * Eigen::AngleAxisd(0.0, Vec3d::UnitX())) + , m_rotation_matrix(Slic3r::Matrix3d::Identity()) { m_rotation_gizmo.use_only_grabbers(); m_group_id = 3; @@ -518,16 +516,14 @@ std::string GLGizmoCut3D::on_get_name() const return _u8L("Cut"); } -void GLGizmoCut3D::on_set_state() +void GLGizmoCut3D::on_set_state() { if (get_state() == On) { update_bb(); - m_selected.clear(); if (CommonGizmosDataObjects::SelectionInfo* selection = m_c->selection_info()) { - const CutConnectors& connectors = selection->model_object()->cut_connectors; - for (size_t i = 0; i < connectors.size(); ++i) - m_selected.push_back(false); + m_selected.clear(); + m_selected.resize(selection->model_object()->cut_connectors.size(), false); } } m_rotation_gizmo.set_center(m_plane_center); @@ -811,8 +807,6 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoCut3D::render_connectors(bool picking) { - const Selection& selection = m_parent.get_selection(); - #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_SHADERS_ATTRIBUTES GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr"); @@ -840,7 +834,8 @@ void GLGizmoCut3D::render_connectors(bool picking) #endif // ENABLE_GL_SHADERS_ATTRIBUTES ColorRGBA render_color; - const CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; + const ModelObject* mo = m_c->selection_info()->model_object(); + const CutConnectors& connectors = mo->cut_connectors; size_t cache_size = connectors.size(); for (size_t i = 0; i < cache_size; ++i) { @@ -863,9 +858,14 @@ void GLGizmoCut3D::render_connectors(bool picking) const_cast(&m_connector_shape)->set_color(-1, render_color); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + // recalculate connector position to world position + Vec3d pos = connector.pos; + pos += mo->instances[m_c->selection_info()->get_active_instance()]->get_offset(); + pos[Z] += m_c->selection_info()->get_sla_shift(); + #if ENABLE_GL_SHADERS_ATTRIBUTES const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform( - Vec3d(connector.pos.x(), connector.pos.y(), connector.pos.z()), + Vec3d(pos.x(), pos.y(), pos.z()), m_rotation_gizmo.get_rotation(), Vec3d(connector.radius, connector.radius, connector.height), Vec3d::Ones() @@ -874,7 +874,7 @@ void GLGizmoCut3D::render_connectors(bool picking) shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #else glsafe(::glPushMatrix()); - glsafe(::glTranslatef(connector.pos.x(), connector.pos.y(), connector.pos.z())); + glsafe(::glTranslatef(pos.x(), pos.y(), pos.z())); const Vec3d& angles = m_rotation_gizmo.get_rotation(); glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0)); @@ -927,7 +927,6 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) ModelObject* mo = wxGetApp().plater()->model().objects[object_idx]; // update connectors pos as offset of its center before cut performing if (!mo->cut_connectors.empty()) { - const std::string name = _u8L("Connector"); for (CutConnector& connector : mo->cut_connectors) { connector.rotation = m_rotation_gizmo.get_rotation(); @@ -935,15 +934,9 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) Vec3d norm = m_grabbers[0].center - m_plane_center; norm.normalize(); Vec3d shift = norm * (0.5 * connector.height); - - // culculate offset of the connector pos regarding to the instance offset and possible SLA elevation - Vec3d connector_offset = connector.pos - instance_offset; - connector_offset[Z] -= first_glvolume->get_sla_shift_z(); - - // Update connector pos. It will be used as a center of created modifiers - connector.pos = connector_offset + shift; + connector.pos += shift; } - mo->apply_cut_connectors(name, CutConnectorAttributes(CutConnectorType(m_connector_type), CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id))); + mo->apply_cut_connectors(_u8L("Connector"), CutConnectorAttributes(CutConnectorType(m_connector_type), CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id))); } wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(), @@ -963,9 +956,6 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) // Return false if no intersection was found, true otherwise. bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, std::pair& pos_and_normal) { - if (!m_c->raycaster()->raycaster()) - return false; - const float sla_shift = m_c->selection_info()->get_sla_shift(); const ModelObject* mo = m_c->selection_info()->model_object(); @@ -986,8 +976,13 @@ bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, std::pair camera, hit, normal, m_c->object_clipper()->get_clipping_plane(), nullptr, &clipping_plane_was_hit); if (clipping_plane_was_hit) { + // recalculate hit to object's local position + Vec3d hit_d = hit.cast(); + hit_d -= mi->get_offset(); + hit_d[Z] -= sla_shift; + // Return both the point and the facet normal. - pos_and_normal = std::make_pair(hit.cast(), normal.cast()); + pos_and_normal = std::make_pair(hit_d, normal.cast()); return true; } } @@ -1037,15 +1032,15 @@ void GLGizmoCut3D::update_model_object() const bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) { - if (is_dragging() || action != SLAGizmoEventType::LeftDown) + if (is_dragging()) return false; - ModelObject *mo = m_c->selection_info()->model_object(); + CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; const Camera& camera = wxGetApp().plater()->get_camera(); int mesh_id = -1; - // left down without selection rectangle - place point on the mesh: + // left down without selection rectangle - place connector on the cut plane: if (action == SLAGizmoEventType::LeftDown && /*!m_selection_rectangle.is_dragging() && */!shift_down) { // If any point is in hover state, this should initiate its move - return control back to GLCanvas: if (m_hover_id != -1) @@ -1059,12 +1054,12 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi const Vec3d& normal = pos_and_normal.second; // The clipping plane was clicked, hit containts coordinates of the hit in world coords. std::cout << hit.x() << "\t" << hit.y() << "\t" << hit.z() << std::endl; - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add pin")); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector")); - mo->cut_connectors.emplace_back(hit, -normal, float(m_connector_size * 0.5), float(m_connector_depth_ratio)); + connectors.emplace_back(hit, m_rotation_gizmo.get_rotation(), float(m_connector_size * 0.5), float(m_connector_depth_ratio)); update_model_object(); m_selected.push_back(false); - assert(m_selected.size() == mo->cut_connectors.size()); + assert(m_selected.size() == connectors.size()); m_parent.set_as_dirty(); m_wait_for_up_event = true; @@ -1074,6 +1069,22 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi } return true; } + else if (action == SLAGizmoEventType::RightDown && !shift_down) { + // If any point is in hover state, this should initiate its move - return control back to GLCanvas: + if (m_hover_id < m_connectors_group_id) + return false; + + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Delete connector")); + + size_t connector_id = m_hover_id - m_connectors_group_id; + connectors.erase(connectors.begin() + connector_id); + update_model_object(); + m_selected.erase(m_selected.begin() + connector_id); + assert(m_selected.size() == connectors.size()); + m_parent.set_as_dirty(); + + return true; + } return false; }