diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 00c489ac13..ed341dfc66 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1465,6 +1465,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const // Displacement (in instance coordinates) to be applied to place the upper parts Vec3d local_displace = Vec3d::Zero(); + Vec3d local_dowels_displace = Vec3d::Zero(); for (ModelVolume* volume : volumes) { const auto volume_matrix = volume->get_matrix(); @@ -1493,6 +1494,9 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const ModelVolume* vol = dowels->add_volume(*volume); vol->set_type(ModelVolumeType::MODEL_PART); + + // Compute the displacement (in instance coordinates) to be applied to place the dowels + local_dowels_displace = lower->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(1.0, 1.0, 0.0)); } } else @@ -1580,8 +1584,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const obj_instance->set_transformation(Geometry::Transformation()); obj_instance->set_offset(offset + displace); - if (i != instance) - obj_instance->set_rotation(Vec3d(0.0, 0.0, rot_z)); + obj_instance->set_rotation(Vec3d(attributes.has(ModelObjectCutAttribute::FlipUpper) ? Geometry::deg2rad(180.0) : 0.0, 0.0, i == instance ? 0.0 : rot_z)); } res.push_back(upper); @@ -1627,10 +1630,15 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const for (size_t i = 0; i < instances.size(); ++i) { auto& obj_instance = dowels->instances[i]; const Vec3d offset = obj_instance->get_offset(); - const double rot_z = obj_instance->get_rotation().z(); + Vec3d rotation = Vec3d::Zero(); + if (i != instance) + rotation[Z] = obj_instance->get_rotation().z(); + + const Vec3d displace = Geometry::assemble_transform(Vec3d::Zero(), rotation) * local_dowels_displace; + obj_instance->set_transformation(Geometry::Transformation()); - obj_instance->set_offset(offset); - obj_instance->set_rotation(Vec3d(0.0, 0.0, i == instance ? 0.0 : rot_z)); + obj_instance->set_offset(offset + displace); + obj_instance->set_rotation(rotation); } res.push_back(dowels); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c8ae063ecd..b3c5b47db1 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -266,7 +266,7 @@ enum class CutConnectorType : int { enum class CutConnectorStyle : int { Prizm - , Frustrum + , Frustum //,Claw }; @@ -304,7 +304,7 @@ enum class ModelVolumeType : int { SUPPORT_ENFORCER, }; -enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower, CreateDowels }; +enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipUpper, FlipLower, CreateDowels }; using ModelObjectCutAttributes = enum_bitmask; ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 411cebbb55..be040e7292 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -43,7 +43,7 @@ GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, m_connector_modes = { _u8L("Auto"), _u8L("Manual") }; m_connector_types = { _u8L("Plug"), _u8L("Dowel") }; - m_connector_styles = { _u8L("Prizm"), _u8L("Frustrum") + m_connector_styles = { _u8L("Prizm"), _u8L("Frustum") // , _u8L("Claw") }; @@ -750,24 +750,54 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) } ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("After cut")); + m_imgui->text(_L("After cut") + ": "); + bool keep = true; + ImGui::SameLine(m_label_width); + m_imgui->text(_L("Upper part")); + ImGui::SameLine(2*m_label_width); m_imgui->disabled_begin(!connectors.empty()); - - bool keep = true; - m_imgui->checkbox(_L("Keep upper part"), connectors.empty() ? m_keep_upper : keep); - m_imgui->text(""); - ImGui::SameLine(m_label_width); - m_imgui->checkbox(_L("Keep lower part"), connectors.empty() ? m_keep_lower : keep); - m_imgui->text(""); - + m_imgui->checkbox(_L("Keep") + "##upper", connectors.empty() ? m_keep_upper : keep); + m_imgui->disabled_end(); + ImGui::SameLine(); + m_imgui->disabled_begin(!m_keep_upper); + m_imgui->checkbox(_L("Flip") + "##upper", m_rotate_upper); m_imgui->disabled_end(); + m_imgui->text(""); ImGui::SameLine(m_label_width); + m_imgui->text(_L("Lower part")); + ImGui::SameLine(2*m_label_width); + + m_imgui->disabled_begin(!connectors.empty()); + m_imgui->checkbox(_L("Keep") + "##lower", connectors.empty() ? m_keep_lower : keep); + m_imgui->disabled_end(); + ImGui::SameLine(); m_imgui->disabled_begin(!m_keep_lower); - m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower); + m_imgui->checkbox(_L("Flip") + "##lower", m_rotate_lower); m_imgui->disabled_end(); + + //m_imgui->disabled_begin(!connectors.empty()); + + //bool keep = true; + //m_imgui->checkbox(_L("Keep upper part"), connectors.empty() ? m_keep_upper : keep); + //m_imgui->text(""); + //ImGui::SameLine(m_label_width); + //m_imgui->checkbox(_L("Keep lower part"), connectors.empty() ? m_keep_lower : keep); + + //m_imgui->disabled_end(); + + //m_imgui->disabled_begin(!m_keep_upper); + //m_imgui->text(""); + //ImGui::SameLine(m_label_width); + //m_imgui->checkbox(_L("Rotate upper part upwards"), m_rotate_upper); + //m_imgui->disabled_end(); + //m_imgui->disabled_begin(!m_keep_lower); + //m_imgui->text(""); + //ImGui::SameLine(m_label_width); + //m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower); + //m_imgui->disabled_end(); } m_imgui->disabled_begin(!m_keep_lower || !m_keep_upper); @@ -978,16 +1008,16 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) for (CutConnector& connector : mo->cut_connectors) { connector.rotation = m_rotation_gizmo.get_rotation(); - if (m_connector_style == size_t(CutConnectorStyle::Prizm)) { - if (m_connector_type == CutConnectorType::Dowel) + if (m_connector_type == CutConnectorType::Dowel) { + if (m_connector_style == size_t(CutConnectorStyle::Prizm)) connector.height *= 2; - else { - // culculate shift of the connector center regarding to the position on the cut plane - Vec3d norm = m_grabbers[0].center - m_plane_center; - norm.normalize(); - Vec3d shift = norm * (0.5 * connector.height); - connector.pos += shift; - } + } + else { + // culculate shift of the connector center regarding to the position on the cut plane + Vec3d norm = m_grabbers[0].center - m_plane_center; + norm.normalize(); + Vec3d shift = norm * (0.5 * connector.height); + connector.pos += shift; } } mo->apply_cut_connectors(_u8L("Connector"), CutConnectorAttributes(CutConnectorType(m_connector_type), CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id))); @@ -998,6 +1028,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(), only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) | only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) | + only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) | only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) | only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels)); m_selected.clear(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 57be3c739f..99bc66d5ef 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -40,6 +40,7 @@ class GLGizmoCut3D : public GLGizmoBase bool m_keep_upper{ true }; bool m_keep_lower{ true }; + bool m_rotate_upper{ false }; bool m_rotate_lower{ false }; bool m_hide_cut_plane{ false };