mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 22:05:56 +08:00
Cut WIP:
* Processed Auto/Manual connetor's mode * Processed Dowel type of connectors * Added TriangeMesh::its_make_frustum_dowel
This commit is contained in:
parent
9658c9c6b7
commit
301d0d5288
@ -712,6 +712,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, ModelVolumeType t
|
||||
ModelVolume* v = new ModelVolume(this, other);
|
||||
if (type != ModelVolumeType::INVALID && v->type() != type)
|
||||
v->set_type(type);
|
||||
v->source.is_connector = other.source.is_connector;
|
||||
this->volumes.push_back(v);
|
||||
// The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull.
|
||||
// v->center_geometry_after_creation();
|
||||
@ -1336,29 +1337,42 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr
|
||||
return res;
|
||||
}
|
||||
|
||||
indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes connector_attributes)
|
||||
{
|
||||
indexed_triangle_set connector_mesh;
|
||||
|
||||
int sectorCount;
|
||||
switch (CutConnectorShape(connector_attributes.shape)) {
|
||||
case CutConnectorShape::Triangle:
|
||||
sectorCount = 3;
|
||||
break;
|
||||
case CutConnectorShape::Square:
|
||||
sectorCount = 4;
|
||||
break;
|
||||
case CutConnectorShape::Circle:
|
||||
sectorCount = 360;
|
||||
break;
|
||||
case CutConnectorShape::Hexagon:
|
||||
sectorCount = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
if (connector_attributes.style == CutConnectorStyle::Prizm)
|
||||
connector_mesh = its_make_cylinder(1.0, 1.0, (2 * PI / sectorCount));
|
||||
else if (connector_attributes.type == CutConnectorType::Plug)
|
||||
connector_mesh = its_make_cone(1.0, 1.0, (2 * PI / sectorCount));
|
||||
else
|
||||
connector_mesh = its_make_frustum_dowel(1.0, 1.0, sectorCount);
|
||||
|
||||
return connector_mesh;
|
||||
}
|
||||
|
||||
void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes)
|
||||
{
|
||||
if (cut_connectors.empty())
|
||||
return;
|
||||
|
||||
bool is_prizm = connector_attributes.style == CutConnectorStyle::Prizm;
|
||||
const std::function<indexed_triangle_set(double, double, double)>& its_make_shape = is_prizm ? its_make_cylinder : its_make_cone;
|
||||
|
||||
indexed_triangle_set connector_mesh;
|
||||
switch (CutConnectorShape(connector_attributes.shape)) {
|
||||
case CutConnectorShape::Triangle:
|
||||
connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 3));
|
||||
break;
|
||||
case CutConnectorShape::Square:
|
||||
connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 4));
|
||||
break;
|
||||
case CutConnectorShape::Circle:
|
||||
connector_mesh = its_make_shape(1.0, 1.0, 2 * PI / 360);
|
||||
break;
|
||||
case CutConnectorShape::Hexagon:
|
||||
connector_mesh = its_make_shape(1.0, 1.0, (2 * PI / 6));
|
||||
break;
|
||||
}
|
||||
indexed_triangle_set connector_mesh = get_connector_mesh(connector_attributes);
|
||||
|
||||
size_t connector_id = 0;
|
||||
|
||||
@ -1393,6 +1407,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
||||
// Clone the object to duplicate instances, materials etc.
|
||||
ModelObject* upper = attributes.has(ModelObjectCutAttribute::KeepUpper) ? ModelObject::new_clone(*this) : nullptr;
|
||||
ModelObject* lower = attributes.has(ModelObjectCutAttribute::KeepLower) ? ModelObject::new_clone(*this) : nullptr;
|
||||
ModelObject* dowels = attributes.has(ModelObjectCutAttribute::CreateDowels) ? ModelObject::new_clone(*this) : nullptr;
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||
upper->set_model(nullptr);
|
||||
@ -1412,6 +1427,15 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
||||
lower->input_file.clear();
|
||||
}
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) {
|
||||
dowels->set_model(nullptr);
|
||||
dowels->sla_support_points.clear();
|
||||
dowels->sla_drain_holes.clear();
|
||||
dowels->sla_points_status = sla::PointsStatus::NoPoints;
|
||||
dowels->clear_volumes();
|
||||
dowels->input_file.clear();
|
||||
}
|
||||
|
||||
// Because transformations are going to be applied to meshes directly,
|
||||
// we reset transformation of all instances and volumes,
|
||||
// except for translation and Z-rotation on instances, which are preserved
|
||||
@ -1450,29 +1474,31 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
||||
volume->mmu_segmentation_facets.reset();
|
||||
|
||||
if (!volume->is_model_part()) {
|
||||
// Modifiers are not cut, but we still need to add the instance transformation
|
||||
// to the modifier volume transformation to preserve their shape properly.
|
||||
// But if this modifier is a connector, then just set volume transformation
|
||||
if (volume->source.is_connector)
|
||||
volume->set_transformation(Geometry::Transformation(volume_matrix));
|
||||
else
|
||||
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
||||
|
||||
ModelVolume* vol = { nullptr };
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||
ModelVolume* vol = upper->add_volume(*volume);
|
||||
if (volume->source.is_connector)
|
||||
vol->source.is_connector = true;
|
||||
}
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
||||
ModelVolume* vol = lower->add_volume(*volume);
|
||||
if (volume->source.is_connector) {
|
||||
vol->source.is_connector = true;
|
||||
// for lower part change type of conector from NEGATIVE_VOLUME to MODEL_PART
|
||||
if (vol->type() == ModelVolumeType::NEGATIVE_VOLUME)
|
||||
if (volume->source.is_connector) {
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
||||
ModelVolume* vol = upper->add_volume(*volume);
|
||||
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
||||
ModelVolume* vol = lower->add_volume(*volume);
|
||||
if (!attributes.has(ModelObjectCutAttribute::CreateDowels))
|
||||
// for lower part change type of connector from NEGATIVE_VOLUME to MODEL_PART if this connector is a plug
|
||||
vol->set_type(ModelVolumeType::MODEL_PART);
|
||||
}
|
||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) {
|
||||
// add one more solid part same as connector if this connector is a dowel
|
||||
// But discard rotation and Z-offset for this volume
|
||||
volume->set_rotation(Vec3d::Zero());
|
||||
Vec3d offset = volume->get_offset();
|
||||
offset[Z] = 0.0;
|
||||
volume->set_offset(offset);
|
||||
|
||||
ModelVolume* vol = dowels->add_volume(*volume);
|
||||
vol->set_type(ModelVolumeType::MODEL_PART);
|
||||
}
|
||||
}
|
||||
else
|
||||
// Modifiers are not cut, but we still need to add the instance transformation
|
||||
// to the modifier volume transformation to preserve their shape properly.
|
||||
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
||||
}
|
||||
else if (!volume->mesh().empty()
|
||||
// && !volume->source.is_connector // we don't allow to cut a connectors
|
||||
@ -1584,6 +1610,32 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
||||
res.push_back(lower);
|
||||
}
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels) && dowels->volumes.size() > 0) {
|
||||
if (!dowels->origin_translation.isApprox(Vec3d::Zero()) && instances[instance]->get_offset().isApprox(Vec3d::Zero())) {
|
||||
dowels->center_around_origin();
|
||||
dowels->translate_instances(-dowels->origin_translation);
|
||||
dowels->origin_translation = Vec3d::Zero();
|
||||
}
|
||||
else {
|
||||
dowels->invalidate_bounding_box();
|
||||
dowels->center_around_origin();
|
||||
}
|
||||
|
||||
dowels->name += "-Dowels";
|
||||
|
||||
// Reset instance transformation except offset and Z-rotation
|
||||
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();
|
||||
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));
|
||||
}
|
||||
|
||||
res.push_back(dowels);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
|
||||
|
||||
return res;
|
||||
|
@ -304,7 +304,7 @@ enum class ModelVolumeType : int {
|
||||
SUPPORT_ENFORCER,
|
||||
};
|
||||
|
||||
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower };
|
||||
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower, CreateDowels };
|
||||
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
|
||||
ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute);
|
||||
|
||||
@ -432,6 +432,7 @@ public:
|
||||
size_t facets_count() const;
|
||||
size_t parts_count() const;
|
||||
ModelObjectPtrs cut(size_t instance, coordf_t z, ModelObjectCutAttributes attributes);
|
||||
static indexed_triangle_set get_connector_mesh(CutConnectorAttributes connector_attributes);
|
||||
void apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes);
|
||||
ModelObjectPtrs cut(size_t instance, const Vec3d& cut_center, const Vec3d& cut_rotation, ModelObjectCutAttributes attributes);
|
||||
void split(ModelObjectPtrs* new_objects);
|
||||
|
@ -1053,6 +1053,61 @@ indexed_triangle_set its_make_sphere(double radius, double fa)
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// Generates mesh for a frustum dowel centered about the origin, using the count of sectors
|
||||
// Note: This function uses code for sphere generation, but for stackCount = 2;
|
||||
indexed_triangle_set its_make_frustum_dowel(double radius, double h, int sectorCount)
|
||||
{
|
||||
int stackCount = 2;
|
||||
float sectorStep = float(2. * M_PI / sectorCount);
|
||||
float stackStep = float(M_PI / stackCount);
|
||||
|
||||
indexed_triangle_set mesh;
|
||||
auto& vertices = mesh.vertices;
|
||||
vertices.reserve((stackCount - 1) * sectorCount + 2);
|
||||
for (int i = 0; i <= stackCount; ++i) {
|
||||
// from pi/2 to -pi/2
|
||||
double stackAngle = 0.5 * M_PI - stackStep * i;
|
||||
double xy = radius * cos(stackAngle);
|
||||
double z = radius * sin(stackAngle);
|
||||
if (i == 0 || i == stackCount)
|
||||
vertices.emplace_back(Vec3f(float(xy), 0.f, float(h * sin(stackAngle))));
|
||||
else
|
||||
for (int j = 0; j < sectorCount; ++j) {
|
||||
// from 0 to 2pi
|
||||
double sectorAngle = sectorStep * j;
|
||||
vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast<float>());
|
||||
}
|
||||
}
|
||||
|
||||
auto& facets = mesh.indices;
|
||||
facets.reserve(2 * (stackCount - 1) * sectorCount);
|
||||
for (int i = 0; i < stackCount; ++i) {
|
||||
// Beginning of current stack.
|
||||
int k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount);
|
||||
int k1_first = k1;
|
||||
// Beginning of next stack.
|
||||
int k2 = (i == 0) ? 1 : (k1 + sectorCount);
|
||||
int k2_first = k2;
|
||||
for (int j = 0; j < sectorCount; ++j) {
|
||||
// 2 triangles per sector excluding first and last stacks
|
||||
int k1_next = k1;
|
||||
int k2_next = k2;
|
||||
if (i != 0) {
|
||||
k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1);
|
||||
facets.emplace_back(k1, k2, k1_next);
|
||||
}
|
||||
if (i + 1 != stackCount) {
|
||||
k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1);
|
||||
facets.emplace_back(k1_next, k2, k2_next);
|
||||
}
|
||||
k1 = k1_next;
|
||||
k2 = k2_next;
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
indexed_triangle_set its_convex_hull(const std::vector<Vec3f> &pts)
|
||||
{
|
||||
std::vector<Vec3f> dst_vertices;
|
||||
|
@ -302,6 +302,7 @@ indexed_triangle_set its_make_cube(double x, double y, double z);
|
||||
indexed_triangle_set its_make_prism(float width, float length, float height);
|
||||
indexed_triangle_set its_make_cylinder(double r, double h, double fa=(2*PI/360));
|
||||
indexed_triangle_set its_make_cone(double r, double h, double fa=(2*PI/360));
|
||||
indexed_triangle_set its_make_frustum_dowel(double r, double h, int sectorCount);
|
||||
indexed_triangle_set its_make_pyramid(float base, float height);
|
||||
indexed_triangle_set its_make_sphere(double radius, double fa);
|
||||
|
||||
|
@ -326,8 +326,10 @@ void GLGizmoCut3D::render_connect_type_radio_button(CutConnectorType type)
|
||||
{
|
||||
ImGui::SameLine(type == CutConnectorType::Plug ? m_label_width : 2*m_label_width);
|
||||
ImGui::PushItemWidth(m_control_width);
|
||||
if (m_imgui->radio_button(m_connector_types[int(type)], m_connector_type == type))
|
||||
if (m_imgui->radio_button(m_connector_types[size_t(type)], m_connector_type == type)) {
|
||||
m_connector_type = type;
|
||||
update_connector_shape();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_connect_mode_radio_button(CutConnectorMode mode)
|
||||
@ -606,7 +608,7 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
|
||||
set_center(starting_box_center + shift);
|
||||
}
|
||||
|
||||
else if (m_hover_id > m_group_id)
|
||||
else if (m_hover_id > m_group_id && m_connector_mode == CutConnectorMode::Manual)
|
||||
{
|
||||
std::pair<Vec3d, Vec3d> pos_and_normal;
|
||||
if (!unproject_on_cut_plane(data.mouse_pos.cast<double>(), pos_and_normal))
|
||||
@ -669,7 +671,7 @@ void GLGizmoCut3D::on_render()
|
||||
if (!m_hide_cut_plane) {
|
||||
render_cut_plane();
|
||||
render_cut_center_graber();
|
||||
if (m_mode == CutMode::cutPlanar) {
|
||||
if (m_mode == size_t(CutMode::cutPlanar)) {
|
||||
if (m_hover_id < m_group_id)
|
||||
m_rotation_gizmo.render();
|
||||
}
|
||||
@ -716,10 +718,12 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
bool revert_rotation{ false };
|
||||
bool revert_move{ false };
|
||||
|
||||
if (m_mode <= CutMode::cutByLine) {
|
||||
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
|
||||
|
||||
if (m_mode <= size_t(CutMode::cutByLine)) {
|
||||
ImGui::Separator();
|
||||
|
||||
if (m_mode == CutMode::cutPlanar) {
|
||||
if (m_mode == size_t(CutMode::cutPlanar)) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Move center"));
|
||||
revert_move = render_revert_button("move");
|
||||
@ -748,11 +752,18 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("After cut"));
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->checkbox(_L("Keep upper part"), m_keep_upper);
|
||||
|
||||
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"), m_keep_lower);
|
||||
m_imgui->checkbox(_L("Keep lower part"), connectors.empty() ? m_keep_lower : keep);
|
||||
m_imgui->text("");
|
||||
|
||||
m_imgui->disabled_end();
|
||||
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->disabled_begin(!m_keep_lower);
|
||||
m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower);
|
||||
@ -779,7 +790,6 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
|
||||
update_connector_shape();
|
||||
|
||||
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
|
||||
if (render_double_input(_u8L("Depth ratio"), m_connector_depth_ratio))
|
||||
for (auto& connector : connectors)
|
||||
connector.height = float(m_connector_depth_ratio);
|
||||
@ -829,6 +839,9 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
|
||||
void GLGizmoCut3D::render_connectors(bool picking)
|
||||
{
|
||||
if (m_connector_mode == CutConnectorMode::Auto)
|
||||
return;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
|
||||
@ -863,6 +876,9 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
const Vec3d& instance_offset = mo->instances[m_c->selection_info()->get_active_instance()]->get_offset();
|
||||
const float sla_shift = m_c->selection_info()->get_sla_shift();
|
||||
|
||||
const ClippingPlane* cp = m_c->object_clipper()->get_clipping_plane();
|
||||
const Vec3d& normal = cp ? cp->get_normal() : Vec3d::Ones();
|
||||
|
||||
for (size_t i = 0; i < cache_size; ++i) {
|
||||
const CutConnector& connector = connectors[i];
|
||||
const bool& point_selected = m_selected[i];
|
||||
@ -883,15 +899,21 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
const_cast<GLModel*>(&m_connector_shape)->set_color(-1, render_color);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
double height = connector.height;
|
||||
// recalculate connector position to world position
|
||||
Vec3d pos = connector.pos + instance_offset;
|
||||
if (m_connector_type == CutConnectorType::Dowel &&
|
||||
m_connector_style == size_t(CutConnectorStyle::Prizm)) {
|
||||
pos -= height * normal;
|
||||
height *= 2;
|
||||
}
|
||||
pos[Z] += sla_shift;
|
||||
|
||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(
|
||||
Vec3d(pos.x(), pos.y(), pos.z()),
|
||||
m_rotation_gizmo.get_rotation(),
|
||||
Vec3d(connector.radius, connector.radius, connector.height),
|
||||
Vec3d(connector.radius, connector.radius, height),
|
||||
Vec3d::Ones()
|
||||
);
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
@ -906,7 +928,7 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
|
||||
|
||||
glsafe(::glTranslated(0., 0., -0.5*connector.height));
|
||||
glsafe(::glScaled(connector.radius, connector.radius, connector.height));
|
||||
glsafe(::glScaled(connector.radius, connector.radius, height));
|
||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
|
||||
m_connector_shape.render();
|
||||
@ -947,26 +969,37 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||
Vec3d cut_center_offset = m_plane_center - instance_offset;
|
||||
cut_center_offset[Z] -= first_glvolume->get_sla_shift_z();
|
||||
|
||||
bool create_dowels_as_separate_object = false;
|
||||
if (0.0 < object_cut_z && can_perform_cut()) {
|
||||
ModelObject* mo = wxGetApp().plater()->model().objects[object_idx];
|
||||
const bool has_connectors = !mo->cut_connectors.empty();
|
||||
// update connectors pos as offset of its center before cut performing
|
||||
if (!mo->cut_connectors.empty()) {
|
||||
if (has_connectors && m_connector_mode == CutConnectorMode::Manual) {
|
||||
for (CutConnector& connector : mo->cut_connectors) {
|
||||
connector.rotation = m_rotation_gizmo.get_rotation();
|
||||
|
||||
// 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;
|
||||
if (m_connector_style == size_t(CutConnectorStyle::Prizm)) {
|
||||
if (m_connector_type == CutConnectorType::Dowel)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
mo->apply_cut_connectors(_u8L("Connector"), CutConnectorAttributes(CutConnectorType(m_connector_type), CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id)));
|
||||
if (m_connector_type == CutConnectorType::Dowel)
|
||||
create_dowels_as_separate_object = true;
|
||||
}
|
||||
|
||||
wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(),
|
||||
only_if(m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
||||
only_if(m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower));
|
||||
only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
||||
only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
|
||||
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels));
|
||||
m_selected.clear();
|
||||
}
|
||||
else {
|
||||
@ -1025,24 +1058,7 @@ void GLGizmoCut3D::update_connector_shape()
|
||||
if (m_connector_shape.is_initialized())
|
||||
m_connector_shape.reset();
|
||||
|
||||
bool is_prizm = m_connector_style == size_t(CutConnectorStyle::Prizm);
|
||||
const std::function<indexed_triangle_set(double, double, double)>& its_make_shape = is_prizm ? its_make_cylinder : its_make_cone;
|
||||
|
||||
|
||||
switch (CutConnectorShape(m_connector_shape_id)) {
|
||||
case CutConnectorShape::Triangle:
|
||||
m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 3)));
|
||||
break;
|
||||
case CutConnectorShape::Square:
|
||||
m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 4)));
|
||||
break;
|
||||
case CutConnectorShape::Circle:
|
||||
m_connector_shape.init_from(its_make_shape(1.0, 1.0, 2 * PI / 360));
|
||||
break;
|
||||
case CutConnectorShape::Hexagon:
|
||||
m_connector_shape.init_from(its_make_shape(1.0, 1.0, (2 * PI / 6)));
|
||||
break;
|
||||
}
|
||||
m_connector_shape.init_from(ModelObject::get_connector_mesh({ m_connector_type, CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id) }));
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::update_model_object() const
|
||||
@ -1056,7 +1072,7 @@ 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())
|
||||
if (is_dragging() || m_connector_mode == CutConnectorMode::Auto || (!m_keep_upper || !m_keep_lower))
|
||||
return false;
|
||||
|
||||
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
|
||||
|
@ -59,7 +59,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
Matrix3d m_rotation_matrix;
|
||||
Vec3d m_rotations{ Vec3d::Zero() };
|
||||
|
||||
enum CutMode {
|
||||
enum class CutMode {
|
||||
cutPlanar
|
||||
, cutByLine
|
||||
, cutGrig
|
||||
@ -67,16 +67,16 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
//,cutModular
|
||||
};
|
||||
|
||||
enum CutConnectorMode {
|
||||
enum class CutConnectorMode {
|
||||
Auto
|
||||
, Manual
|
||||
};
|
||||
|
||||
std::vector<std::string> m_modes;
|
||||
size_t m_mode{ size_t(cutPlanar) };
|
||||
size_t m_mode{ size_t(CutMode::cutPlanar) };
|
||||
|
||||
std::vector<std::string> m_connector_modes;
|
||||
CutConnectorMode m_connector_mode{ Auto };
|
||||
CutConnectorMode m_connector_mode{ CutConnectorMode::Manual };
|
||||
|
||||
std::vector<std::string> m_connector_types;
|
||||
CutConnectorType m_connector_type;
|
||||
|
Loading…
x
Reference in New Issue
Block a user