mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 09:46:05 +08:00
Cut: next UI improvements
This commit is contained in:
parent
f7284a6569
commit
76784441be
@ -28,20 +28,6 @@ static const ColorRGBA GRABBER_COLOR = ColorRGBA::ORANGE();
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
{
|
||||
m_modes = { _u8L("Planar"), _u8L("Grid")
|
||||
// , _u8L("Radial"), _u8L("Modular")
|
||||
};
|
||||
|
||||
m_connector_types = { _u8L("Plug"), _u8L("Dowel") };
|
||||
|
||||
m_connector_styles = { _u8L("Prizm"), _u8L("Frustrum")
|
||||
// , _u8L("Claw")
|
||||
};
|
||||
|
||||
m_connector_shapes = { _u8L("Triangle"), _u8L("Square"), _u8L("Circle"), _u8L("Hexagon")
|
||||
// , _u8L("D-shape")
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
std::string GLGizmoCut::get_tooltip() const
|
||||
@ -56,7 +42,7 @@ std::string GLGizmoCut::get_tooltip() const
|
||||
bool GLGizmoCut::on_init()
|
||||
{
|
||||
m_grabbers.emplace_back();
|
||||
m_shortcut_key = WXK_CONTROL_C;
|
||||
// m_shortcut_key = WXK_CONTROL_C;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -68,7 +54,7 @@ std::string GLGizmoCut::on_get_name() const
|
||||
void GLGizmoCut::on_set_state()
|
||||
{
|
||||
// Reset m_cut_z on gizmo activation
|
||||
if (get_state() == On)
|
||||
if (get_state() == On && m_cut_z == 0.0)
|
||||
m_cut_z = bounding_box().center().z();
|
||||
}
|
||||
|
||||
@ -107,14 +93,20 @@ void GLGizmoCut::on_render()
|
||||
|
||||
update_contours();
|
||||
|
||||
const float min_x = box.min.x() - Margin;
|
||||
const float max_x = box.max.x() + Margin;
|
||||
const float min_y = box.min.y() - Margin;
|
||||
const float max_y = box.max.y() + Margin;
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
//const float min_x = box.min.x() - Margin - plane_center.x();
|
||||
//const float max_x = box.max.x() + Margin - plane_center.x();
|
||||
//const float min_y = box.min.y() - Margin - plane_center.y();
|
||||
//const float max_y = box.max.y() + Margin - plane_center.y();
|
||||
// glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
// glsafe(::glDisable(GL_CULL_FACE));
|
||||
// glsafe(::glEnable(GL_BLEND));
|
||||
// glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
//
|
||||
//#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
//#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
//
|
||||
// glsafe(::glEnable(GL_CULL_FACE));
|
||||
// glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
@ -229,13 +221,80 @@ void GLGizmoCut::on_render()
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z()));
|
||||
// glsafe(::glTranslated(plane_center.x(), plane_center.y(), plane_center.z()));
|
||||
glsafe(::glRotated(Geometry::rad2deg(m_angles.z()), 0.0, 0.0, 1.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(m_angles.y()), 0.0, 1.0, 0.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(m_angles.x()), 1.0, 0.0, 0.0));
|
||||
|
||||
glsafe(::glLineWidth(2.0f));
|
||||
m_cut_contours.contours.render();
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_render_for_picking()
|
||||
{
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
|
||||
}
|
||||
|
||||
void GLGizmoCut::render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx)
|
||||
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
static float last_y = 0.0f;
|
||||
static float last_h = 0.0f;
|
||||
|
||||
m_imgui->begin(_L("Cut"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
const bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
|
||||
|
||||
// adjust window position to avoid overlap the view toolbar
|
||||
const float win_h = ImGui::GetWindowHeight();
|
||||
y = std::min(y, bottom_limit - win_h);
|
||||
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
|
||||
if (last_h != win_h || last_y != y) {
|
||||
// ask canvas for another frame to render the window in the correct position
|
||||
m_imgui->set_requires_extra_frame();
|
||||
if (last_h != win_h)
|
||||
last_h = win_h;
|
||||
if (last_y != y)
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text("Z");
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(m_imgui->get_style_scaling() * 150.0f);
|
||||
|
||||
double cut_z = m_cut_z;
|
||||
if (imperial_units)
|
||||
cut_z *= ObjectManipulation::mm_to_in;
|
||||
ImGui::InputDouble("", &cut_z, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
|
||||
ImGui::SameLine();
|
||||
m_imgui->text(imperial_units ? _L("in") : _L("mm"));
|
||||
|
||||
m_cut_z = cut_z * (imperial_units ? ObjectManipulation::in_to_mm : 1.0);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
m_imgui->checkbox(_L("Keep upper part"), m_keep_upper);
|
||||
m_imgui->checkbox(_L("Keep lower part"), m_keep_lower);
|
||||
m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
m_imgui->disabled_begin((!m_keep_upper && !m_keep_lower) || m_cut_z <= 0.0 || m_max_z <= m_cut_z);
|
||||
const bool cut_clicked = m_imgui->button(_L("Perform cut"));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->end();
|
||||
|
||||
if (cut_clicked && (m_keep_upper || m_keep_lower))
|
||||
perform_cut(m_parent.get_selection());
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx)
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(label);
|
||||
@ -273,7 +332,7 @@ void GLGizmoCut::render_combo(const std::string& label, const std::vector<std::s
|
||||
selection_idx = selection_out;
|
||||
}
|
||||
|
||||
void GLGizmoCut::render_double_input(const std::string& label, double& value_in)
|
||||
void GLGizmoCut3D::render_double_input(const std::string& label, double& value_in)
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(label);
|
||||
@ -291,22 +350,46 @@ void GLGizmoCut::render_double_input(const std::string& label, double& value_in)
|
||||
value_in = value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0);
|
||||
}
|
||||
|
||||
void GLGizmoCut::render_rotation_input(const std::string& label, double& value_in)
|
||||
void GLGizmoCut3D::render_move_center_input(int axis)
|
||||
{
|
||||
m_imgui->text(label);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_axis_names[axis]+":");
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(0.3*m_control_width);
|
||||
|
||||
double value = axis == Z ? m_cut_plane_gizmo.get_cut_z() : 0.0;
|
||||
if (m_imperial_units)
|
||||
value *= ObjectManipulation::mm_to_in;
|
||||
ImGui::InputDouble(("##move_" + m_axis_names[axis]).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::SameLine();
|
||||
|
||||
double value = value_in;
|
||||
if (axis == Z) {
|
||||
double val = value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0);
|
||||
m_cut_plane_gizmo.set_cut_z(val);
|
||||
set_center_z(val);
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_rotation_input(int axis)
|
||||
{
|
||||
m_imgui->text(m_axis_names[axis] + ":");
|
||||
ImGui::SameLine();
|
||||
|
||||
Vec3d rotation = get_rotation();
|
||||
double value = rotation[axis];
|
||||
if (value > 360)
|
||||
value -= 360;
|
||||
|
||||
ImGui::PushItemWidth(0.3*m_control_width);
|
||||
ImGui::InputDouble(("##" + label).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::InputDouble(("##rotate_" + m_axis_names[axis]).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::SameLine();
|
||||
|
||||
value_in = value;
|
||||
rotation[axis] = value;
|
||||
set_rotation(rotation);
|
||||
m_cut_plane_gizmo.set_angles(rotation);
|
||||
}
|
||||
|
||||
void GLGizmoCut::render_radio_button(ConnectorType type)
|
||||
void GLGizmoCut3D::render_connect_type_radio_button(ConnectorType type)
|
||||
{
|
||||
ImGui::SameLine(type == ConnectorType::Plug ? m_label_width : 2*m_label_width);
|
||||
ImGui::PushItemWidth(m_control_width);
|
||||
@ -314,88 +397,93 @@ void GLGizmoCut::render_radio_button(ConnectorType type)
|
||||
m_connector_type = type;
|
||||
}
|
||||
|
||||
|
||||
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
|
||||
void GLGizmoCut3D::render_connect_mode_radio_button(ConnectorMode mode)
|
||||
{
|
||||
static float last_y = 0.0f;
|
||||
static float last_h = 0.0f;
|
||||
ImGui::SameLine(mode == ConnectorMode::Auto ? m_label_width : 2*m_label_width);
|
||||
ImGui::PushItemWidth(m_control_width);
|
||||
if (m_imgui->radio_button(m_connector_modes[int(mode)], m_connector_mode == mode))
|
||||
m_connector_mode = mode;
|
||||
}
|
||||
|
||||
m_imgui->begin(_L("Cut"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
void GLGizmoCut3D::render_cut_plane()
|
||||
{
|
||||
const BoundingBoxf3 box = m_cut_plane_gizmo.bounding_box();
|
||||
Vec3d plane_center = box.center();
|
||||
plane_center.z() = m_cut_plane_gizmo.get_cut_z();
|
||||
|
||||
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
|
||||
m_label_width = m_imgui->get_style_scaling() * 100.0f;
|
||||
m_control_width = m_imgui->get_style_scaling() * 150.0f;
|
||||
const float min_x = box.min.x() - GLGizmoCut::Margin - plane_center.x();
|
||||
const float max_x = box.max.x() + GLGizmoCut::Margin - plane_center.x();
|
||||
const float min_y = box.min.y() - GLGizmoCut::Margin - plane_center.y();
|
||||
const float max_y = box.max.y() + GLGizmoCut::Margin - plane_center.y();
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// adjust window position to avoid overlap the view toolbar
|
||||
const float win_h = ImGui::GetWindowHeight();
|
||||
y = std::min(y, bottom_limit - win_h);
|
||||
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
|
||||
if (last_h != win_h || last_y != y) {
|
||||
// ask canvas for another frame to render the window in the correct position
|
||||
m_imgui->set_requires_extra_frame();
|
||||
if (last_h != win_h)
|
||||
last_h = win_h;
|
||||
if (last_y != y)
|
||||
last_y = y;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
shader->start_using();
|
||||
|
||||
// bool z_changed = std::abs(plane_center.z() - m_old_z) > EPSILON;
|
||||
// m_old_z = plane_center.z();
|
||||
|
||||
Vec3d angles = get_rotation();
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(plane_center.x(), plane_center.y(), plane_center.z()));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
|
||||
|
||||
if (!m_plane.is_initialized()/* || z_changed*/) {
|
||||
m_plane.reset();
|
||||
|
||||
GLModel::InitializationData init_data;
|
||||
GLModel::InitializationData::Entity entity;
|
||||
entity.type = GLModel::PrimitiveType::Triangles;
|
||||
entity.positions.reserve(4);
|
||||
entity.positions.emplace_back(Vec3f(min_x, min_y, 0.0));
|
||||
entity.positions.emplace_back(Vec3f(max_x, min_y, 0.0));
|
||||
entity.positions.emplace_back(Vec3f(max_x, max_y, 0.0));
|
||||
entity.positions.emplace_back(Vec3f(min_x, max_y, 0.0));
|
||||
|
||||
entity.normals.reserve(4);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
entity.normals.emplace_back(Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
entity.indices.reserve(6);
|
||||
entity.indices.emplace_back(0);
|
||||
entity.indices.emplace_back(1);
|
||||
entity.indices.emplace_back(2);
|
||||
entity.indices.emplace_back(2);
|
||||
entity.indices.emplace_back(3);
|
||||
entity.indices.emplace_back(0);
|
||||
|
||||
init_data.entities.emplace_back(entity);
|
||||
m_plane.init_from(init_data);
|
||||
m_plane.set_color(-1, PLANE_COLOR);
|
||||
}
|
||||
|
||||
render_combo(_u8L("Mode"), m_modes, m_mode);
|
||||
m_plane.render();
|
||||
glsafe(::glPopMatrix());
|
||||
#else
|
||||
// Draw the cutting plane
|
||||
::glBegin(GL_QUADS);
|
||||
::glColor4fv(PLANE_COLOR.data());
|
||||
::glVertex3f(min_x, min_y, plane_center.z());
|
||||
::glVertex3f(max_x, min_y, plane_center.z());
|
||||
::glVertex3f(max_x, max_y, plane_center.z());
|
||||
::glVertex3f(min_x, max_y, plane_center.z());
|
||||
glsafe(::glEnd());
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
if (m_mode == CutMode::cutPlanar) {
|
||||
ImGui::Separator();
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
render_double_input("Z", m_cut_z);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Rotation"));
|
||||
ImGui::SameLine(m_label_width);
|
||||
|
||||
render_rotation_input("X:", m_rotation_x);
|
||||
ImGui::SameLine();
|
||||
render_rotation_input("Y:", m_rotation_y);
|
||||
ImGui::SameLine();
|
||||
render_rotation_input("Z:", m_rotation_z);
|
||||
|
||||
ImGui::SameLine();
|
||||
m_imgui->text(_L("°"));
|
||||
|
||||
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->text("");
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->checkbox(_L("Keep lower part"), m_keep_lower);
|
||||
m_imgui->text("");
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->disabled_begin(!m_keep_lower);
|
||||
m_imgui->checkbox(_L("Rotate lower part upwards"), m_rotate_lower);
|
||||
m_imgui->disabled_end();
|
||||
}
|
||||
|
||||
// Connectors section
|
||||
ImGui::Separator();
|
||||
|
||||
m_imgui->text(_L("Connectors"));
|
||||
render_radio_button(ConnectorType::Plug);
|
||||
render_radio_button(ConnectorType::Dowel);
|
||||
|
||||
render_combo(_u8L("Style"), m_connector_styles, m_connector_style);
|
||||
render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape);
|
||||
|
||||
render_double_input(_u8L("Depth ratio"), m_connector_depth_ratio);
|
||||
render_double_input(_u8L("Size"), m_connector_size);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
m_imgui->disabled_begin((!m_keep_upper && !m_keep_lower) || m_cut_z <= 0.0 || m_max_z <= m_cut_z);
|
||||
const bool cut_clicked = m_imgui->button(_L("Perform cut"));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->end();
|
||||
|
||||
if (cut_clicked && (m_keep_upper || m_keep_lower))
|
||||
perform_cut(m_parent.get_selection());
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
void GLGizmoCut::set_cut_z(double cut_z)
|
||||
@ -481,18 +569,28 @@ void GLGizmoCut::update_contours()
|
||||
if (m_cut_contours.object_id != model_object->id() || m_cut_contours.volumes_idxs != volumes_idxs)
|
||||
m_cut_contours.mesh = model_object->raw_mesh();
|
||||
|
||||
m_cut_contours.position = box.center();
|
||||
m_cut_contours.shift = Vec3d::Zero();
|
||||
m_cut_contours.position = Vec3d::Zero();//box.center();
|
||||
m_cut_contours.shift = box.center();//Vec3d::Zero();
|
||||
m_cut_contours.object_id = model_object->id();
|
||||
m_cut_contours.instance_idx = instance_idx;
|
||||
m_cut_contours.volumes_idxs = volumes_idxs;
|
||||
m_cut_contours.contours.reset();
|
||||
|
||||
// addition back transformation
|
||||
Geometry::Transformation m_transformation = Geometry::Transformation();
|
||||
m_transformation.set_offset(-first_glvolume->get_instance_transformation().get_offset());
|
||||
m_transformation.set_rotation(-m_angles);
|
||||
auto cut_params = m_transformation.get_matrix();
|
||||
|
||||
|
||||
MeshSlicingParams slicing_params;
|
||||
slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix();
|
||||
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, m_cut_z, slicing_params);
|
||||
slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix() * cut_params;
|
||||
|
||||
auto cut_z = m_cut_z - box.center().z();
|
||||
|
||||
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, /*m_*/cut_z, slicing_params);
|
||||
if (!polys.empty()) {
|
||||
m_cut_contours.contours.init_from(polys, static_cast<float>(m_cut_z));
|
||||
m_cut_contours.contours.init_from(polys, static_cast<float>(/*m_*/cut_z));
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_cut_contours.contours.set_color(ColorRGBA::WHITE());
|
||||
#else
|
||||
@ -500,13 +598,211 @@ void GLGizmoCut::update_contours()
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
}
|
||||
else if (box.center() != m_cut_contours.position) {
|
||||
m_cut_contours.shift = box.center() - m_cut_contours.position;
|
||||
else if (box.center() != m_cut_contours.shift) {
|
||||
m_cut_contours.shift = box.center();// -m_cut_contours.position;
|
||||
}
|
||||
//else if (box.center() != m_cut_contours.position) {
|
||||
// m_cut_contours.shift = -box.center();// -m_cut_contours.position;
|
||||
//}
|
||||
}
|
||||
else
|
||||
m_cut_contours.contours.reset();
|
||||
}
|
||||
|
||||
GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoRotate3D(parent, icon_filename, sprite_id)
|
||||
, m_cut_plane_gizmo(GLGizmoCut(parent, "", -1))
|
||||
{
|
||||
m_cut_plane_gizmo.set_group_id(3);
|
||||
|
||||
m_modes = { _u8L("Planar"), _u8L("By Line"),_u8L("Grid")
|
||||
// , _u8L("Radial"), _u8L("Modular")
|
||||
};
|
||||
|
||||
m_connector_modes = { _u8L("Auto"), _u8L("Manual") };
|
||||
m_connector_types = { _u8L("Plug"), _u8L("Dowel") };
|
||||
|
||||
m_connector_styles = { _u8L("Prizm"), _u8L("Frustrum")
|
||||
// , _u8L("Claw")
|
||||
};
|
||||
|
||||
m_connector_shapes = { _u8L("Triangle"), _u8L("Square"), _u8L("Circle"), _u8L("Hexagon")
|
||||
// , _u8L("D-shape")
|
||||
};
|
||||
|
||||
m_axis_names = {"X", "Y", "Z"};
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::on_init()
|
||||
{
|
||||
if(!GLGizmoRotate3D::on_init())
|
||||
return false;
|
||||
|
||||
if (!m_cut_plane_gizmo.init())
|
||||
return false;
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_C;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GLGizmoCut3D::on_get_name() const
|
||||
{
|
||||
return _u8L("Cut");
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::on_is_activable() const
|
||||
{
|
||||
return m_cut_plane_gizmo.is_activable();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::on_start_dragging()
|
||||
{
|
||||
GLGizmoRotate3D::on_start_dragging();
|
||||
if (m_hover_id == 3)
|
||||
m_cut_plane_gizmo.start_dragging();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::on_stop_dragging()
|
||||
{
|
||||
GLGizmoRotate3D::on_stop_dragging();
|
||||
if (m_hover_id == 3)
|
||||
m_cut_plane_gizmo.stop_dragging();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::on_render()
|
||||
{
|
||||
render_cut_plane();
|
||||
if (m_mode == CutMode::cutPlanar) {
|
||||
GLGizmoRotate3D::on_render();
|
||||
// if (m_hover_id == -1 || m_hover_id == 3)
|
||||
}
|
||||
m_cut_plane_gizmo.render();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
static float last_y = 0.0f;
|
||||
static float last_h = 0.0f;
|
||||
|
||||
m_imgui->begin(_L("Cut"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
|
||||
m_label_width = m_imgui->get_style_scaling() * 100.0f;
|
||||
m_control_width = m_imgui->get_style_scaling() * 150.0f;
|
||||
|
||||
// adjust window position to avoid overlap the view toolbar
|
||||
const float win_h = ImGui::GetWindowHeight();
|
||||
y = std::min(y, bottom_limit - win_h);
|
||||
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
|
||||
if (last_h != win_h || last_y != y) {
|
||||
// ask canvas for another frame to render the window in the correct position
|
||||
m_imgui->set_requires_extra_frame();
|
||||
if (last_h != win_h)
|
||||
last_h = win_h;
|
||||
if (last_y != y)
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
render_combo(_u8L("Mode"), m_modes, m_mode);
|
||||
|
||||
if (m_mode <= CutMode::cutByLine) {
|
||||
ImGui::Separator();
|
||||
|
||||
if (m_mode == CutMode::cutPlanar) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Move center"));
|
||||
ImGui::SameLine(m_label_width);
|
||||
for (Axis axis : {X, Y, Z})
|
||||
render_move_center_input(axis);
|
||||
m_imgui->text(m_imperial_units ? _L("in") : _L("mm"));
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Rotation"));
|
||||
ImGui::SameLine(m_label_width);
|
||||
for (Axis axis : {X, Y, Z})
|
||||
render_rotation_input(axis);
|
||||
m_imgui->text(_L("°"));
|
||||
}
|
||||
else {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 3*m_control_width);
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Connect some two points of object to cteate a cut plane"));
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
}
|
||||
|
||||
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->text("");
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->checkbox(_L("Keep lower part"), m_keep_lower);
|
||||
m_imgui->text("");
|
||||
ImGui::SameLine(m_label_width);
|
||||
m_imgui->disabled_begin(!m_keep_lower);
|
||||
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);
|
||||
// Connectors section
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Connectors"));
|
||||
|
||||
m_imgui->text(_L("Mode"));
|
||||
render_connect_mode_radio_button(ConnectorMode::Auto);
|
||||
render_connect_mode_radio_button(ConnectorMode::Manual);
|
||||
|
||||
m_imgui->text(_L("Type"));
|
||||
render_connect_type_radio_button(ConnectorType::Plug);
|
||||
render_connect_type_radio_button(ConnectorType::Dowel);
|
||||
|
||||
render_combo(_u8L("Style"), m_connector_styles, m_connector_style);
|
||||
render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape);
|
||||
|
||||
render_double_input(_u8L("Depth ratio"), m_connector_depth_ratio);
|
||||
render_double_input(_u8L("Size"), m_connector_size);
|
||||
|
||||
m_imgui->disabled_end();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
m_imgui->disabled_begin((!m_keep_upper && !m_keep_lower) /*|| m_cut_z <= 0.0 || m_max_z <= m_cut_z*/);
|
||||
const bool cut_clicked = m_imgui->button(_L("Perform cut"));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->end();
|
||||
|
||||
if (cut_clicked && (m_keep_upper || m_keep_lower))
|
||||
perform_cut(m_parent.get_selection());
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||
{
|
||||
const int instance_idx = selection.get_instance_idx();
|
||||
const int object_idx = selection.get_object_idx();
|
||||
|
||||
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
|
||||
|
||||
// m_cut_z is the distance from the bed. Subtract possible SLA elevation.
|
||||
const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const double object_cut_z = m_cut_plane_gizmo.get_cut_z() - first_glvolume->get_sla_shift_z();
|
||||
|
||||
if (0.0 < object_cut_z/* && object_cut_z < m_max_z*/)
|
||||
wxGetApp().plater()->cut(object_idx, instance_idx, object_cut_z,
|
||||
only_if(m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
||||
only_if(m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower));
|
||||
else {
|
||||
// the object is SLA-elevated and the plane is under it.
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define slic3r_GLGizmoCut_hpp_
|
||||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "GLGizmoRotate.hpp"
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/ObjectID.hpp"
|
||||
@ -11,13 +12,11 @@ namespace GUI {
|
||||
|
||||
class GLGizmoCut : public GLGizmoBase
|
||||
{
|
||||
public:
|
||||
static const double Offset;
|
||||
static const double Margin;
|
||||
|
||||
private:
|
||||
double m_cut_z{ 0.0 };
|
||||
double m_rotation_x{ 0.0 };
|
||||
double m_rotation_y{ 0.0 };
|
||||
double m_rotation_z{ 0.0 };
|
||||
double m_max_z{ 0.0 };
|
||||
double m_start_z{ 0.0 };
|
||||
Vec3d m_drag_pos;
|
||||
@ -26,57 +25,11 @@ class GLGizmoCut : public GLGizmoBase
|
||||
bool m_keep_lower{ true };
|
||||
bool m_rotate_lower{ false };
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel m_plane;
|
||||
GLModel m_grabber_connection;
|
||||
float m_old_z{ 0.0f };
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
double m_connector_depth_ratio{ 1.5 };
|
||||
double m_connector_size{ 5.0 };
|
||||
|
||||
float m_label_width{ 150.0 };
|
||||
float m_control_width{ 200.0 };
|
||||
bool m_imperial_units{ false };
|
||||
|
||||
public:
|
||||
enum CutMode {
|
||||
cutPlanar = 0
|
||||
,cutGrig
|
||||
//,cutRadial
|
||||
//,cutModular
|
||||
};
|
||||
|
||||
enum ConnectorType {
|
||||
Plug = 0
|
||||
,Dowel
|
||||
};
|
||||
|
||||
enum ConnectorStyle {
|
||||
Prizm = 0
|
||||
,Frustrum
|
||||
//,Claw
|
||||
};
|
||||
|
||||
enum ConnectorShape {
|
||||
Triangle = 0
|
||||
,Square
|
||||
,Circle
|
||||
,Hexagon
|
||||
// ,D-shape
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::string> m_modes;
|
||||
size_t m_mode{ size_t(cutPlanar) };
|
||||
|
||||
std::vector<std::string> m_connector_types;
|
||||
ConnectorType m_connector_type{ Plug };
|
||||
|
||||
std::vector<std::string> m_connector_styles;
|
||||
size_t m_connector_style{ size_t(Prizm) };
|
||||
|
||||
std::vector<std::string> m_connector_shapes;
|
||||
size_t m_connector_shape{ size_t(Hexagon) };
|
||||
Vec3d m_angles{ Vec3d::Zero() };
|
||||
|
||||
struct CutContours
|
||||
{
|
||||
@ -95,8 +48,9 @@ private:
|
||||
public:
|
||||
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
double get_cut_z() const { return m_cut_z; }
|
||||
void set_cut_z(double cut_z);
|
||||
double get_cut_z() const { return m_cut_z; }
|
||||
void set_cut_z(double cut_z);
|
||||
void set_angles(const Vec3d& angles) { m_angles = angles; }
|
||||
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
@ -113,18 +67,143 @@ protected:
|
||||
virtual void on_render_for_picking() override;
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
void render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx);
|
||||
void render_double_input(const std::string& label, double& value_in);
|
||||
void render_rotation_input(const std::string& label, double& value_in);
|
||||
void render_radio_button(ConnectorType type);
|
||||
|
||||
private:
|
||||
void perform_cut(const Selection& selection);
|
||||
double calc_projection(const Linef3& mouse_ray) const;
|
||||
|
||||
public:
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
void update_contours();
|
||||
};
|
||||
|
||||
class GLGizmoCut3D : public GLGizmoRotate3D
|
||||
{
|
||||
GLGizmoCut m_cut_plane_gizmo;
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel m_plane;
|
||||
float m_old_z{ 0.0f };
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
bool m_keep_upper{ true };
|
||||
bool m_keep_lower{ true };
|
||||
bool m_rotate_lower{ false };
|
||||
|
||||
double m_connector_depth_ratio{ 1.5 };
|
||||
double m_connector_size{ 5.0 };
|
||||
|
||||
float m_label_width{ 150.0 };
|
||||
float m_control_width{ 200.0 };
|
||||
bool m_imperial_units{ false };
|
||||
|
||||
enum CutMode {
|
||||
cutPlanar
|
||||
, cutByLine
|
||||
, cutGrig
|
||||
//,cutRadial
|
||||
//,cutModular
|
||||
};
|
||||
|
||||
enum ConnectorMode {
|
||||
Auto
|
||||
, Manual
|
||||
};
|
||||
|
||||
enum ConnectorType {
|
||||
Plug
|
||||
, Dowel
|
||||
};
|
||||
|
||||
enum ConnectorStyle {
|
||||
Prizm
|
||||
, Frustrum
|
||||
//,Claw
|
||||
};
|
||||
|
||||
enum ConnectorShape {
|
||||
Triangle
|
||||
, Square
|
||||
, Circle
|
||||
, Hexagon
|
||||
//,D-shape
|
||||
};
|
||||
|
||||
std::vector<std::string> m_modes;
|
||||
size_t m_mode{ size_t(cutPlanar) };
|
||||
|
||||
std::vector<std::string> m_connector_modes;
|
||||
ConnectorMode m_connector_mode{ Auto };
|
||||
|
||||
std::vector<std::string> m_connector_types;
|
||||
ConnectorType m_connector_type{ Plug };
|
||||
|
||||
std::vector<std::string> m_connector_styles;
|
||||
size_t m_connector_style{ size_t(Prizm) };
|
||||
|
||||
std::vector<std::string> m_connector_shapes;
|
||||
size_t m_connector_shape{ size_t(Hexagon) };
|
||||
|
||||
std::vector<std::string> m_axis_names;
|
||||
|
||||
public:
|
||||
GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
std::string get_tooltip() const override {
|
||||
std::string tooltip = GLGizmoRotate3D::get_tooltip();
|
||||
if (tooltip.empty())
|
||||
tooltip = m_cut_plane_gizmo.get_tooltip();
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override;
|
||||
void on_set_state() override {
|
||||
GLGizmoRotate3D::on_set_state();
|
||||
m_cut_plane_gizmo.set_state(m_state);
|
||||
}
|
||||
void on_set_hover_id() override {
|
||||
GLGizmoRotate3D::on_set_hover_id();
|
||||
m_cut_plane_gizmo.set_hover_id((m_hover_id == 3) ? 0 : -1);
|
||||
}
|
||||
void on_enable_grabber(unsigned int id) override {
|
||||
GLGizmoRotate3D::on_enable_grabber(id);
|
||||
if (id == 3)
|
||||
m_cut_plane_gizmo.enable_grabber(0);
|
||||
}
|
||||
void on_disable_grabber(unsigned int id) override {
|
||||
GLGizmoRotate3D::on_disable_grabber(id);
|
||||
if (id == 3)
|
||||
m_cut_plane_gizmo.disable_grabber(0);
|
||||
}
|
||||
bool on_is_activable() const override;
|
||||
void on_start_dragging() override;
|
||||
void on_stop_dragging() override;
|
||||
void on_update(const UpdateData& data) override {
|
||||
GLGizmoRotate3D::on_update(data);
|
||||
m_cut_plane_gizmo.update(data);
|
||||
}
|
||||
void on_render() override;
|
||||
void on_render_for_picking() override {
|
||||
GLGizmoRotate3D::on_render_for_picking();
|
||||
m_cut_plane_gizmo.render_for_picking();
|
||||
}
|
||||
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
private:
|
||||
|
||||
void render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx);
|
||||
void render_double_input(const std::string& label, double& value_in);
|
||||
void render_move_center_input(int axis);
|
||||
void render_rotation_input(int axis);
|
||||
void render_connect_mode_radio_button(ConnectorMode mode);
|
||||
void render_connect_type_radio_button(ConnectorType type);
|
||||
|
||||
void render_cut_plane();
|
||||
void perform_cut(const Selection& selection);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -38,6 +38,11 @@ void GLGizmoRotate::set_angle(double angle)
|
||||
m_angle = angle;
|
||||
}
|
||||
|
||||
void GLGizmoRotate::set_center_z(double center_z)
|
||||
{
|
||||
m_center_z = center_z;
|
||||
}
|
||||
|
||||
std::string GLGizmoRotate::get_tooltip() const
|
||||
{
|
||||
std::string axis;
|
||||
@ -60,6 +65,8 @@ void GLGizmoRotate::on_start_dragging()
|
||||
{
|
||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||
m_center = box.center();
|
||||
if (m_center_z >= 0)
|
||||
m_center[Z] = m_center_z;
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
@ -112,6 +119,8 @@ void GLGizmoRotate::on_render()
|
||||
|
||||
if (m_hover_id != 0 && !m_grabbers.front().dragging) {
|
||||
m_center = box.center();
|
||||
if (m_center_z >= 0)
|
||||
m_center[Z] = m_center_z;
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
private:
|
||||
Axis m_axis;
|
||||
double m_angle{ 0.0 };
|
||||
double m_center_z{ -1.0 };
|
||||
Vec3d m_center{ Vec3d::Zero() };
|
||||
float m_radius{ 0.0f };
|
||||
float m_snap_coarse_in_radius{ 0.0f };
|
||||
@ -58,6 +59,7 @@ public:
|
||||
|
||||
double get_angle() const { return m_angle; }
|
||||
void set_angle(double angle);
|
||||
void set_center_z(double center_z);
|
||||
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
@ -101,6 +103,7 @@ public:
|
||||
|
||||
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
|
||||
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
|
||||
void set_center_z(double center_z) { m_gizmos[X].set_center_z(center_z); m_gizmos[Y].set_center_z(center_z); m_gizmos[Z].set_center_z(center_z); }
|
||||
|
||||
std::string get_tooltip() const override {
|
||||
std::string tooltip = m_gizmos[X].get_tooltip();
|
||||
|
@ -97,7 +97,7 @@ bool GLGizmosManager::init()
|
||||
m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, "scale.svg", 1));
|
||||
m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, "rotate.svg", 2));
|
||||
m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, "place.svg", 3));
|
||||
m_gizmos.emplace_back(new GLGizmoCut(m_parent, "cut.svg", 4));
|
||||
m_gizmos.emplace_back(new GLGizmoCut3D(m_parent, "cut.svg", 4));
|
||||
m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", 5));
|
||||
m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 6));
|
||||
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, "fdm_supports.svg", 7));
|
||||
|
Loading…
x
Reference in New Issue
Block a user