mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 03:15:51 +08:00
Cut WIP: set attributes for each connector separately.
+ Allow select/deselect several connectors and apply size/depth for selected group of connectors
This commit is contained in:
parent
0fd29dfec7
commit
e990254d52
@ -1378,7 +1378,7 @@ indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes conn
|
||||
return connector_mesh;
|
||||
}
|
||||
|
||||
void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes)
|
||||
void ModelObject::apply_cut_connectors(const std::string& name)
|
||||
{
|
||||
// discard old connector markers for volumes
|
||||
for (ModelVolume* volume : volumes)
|
||||
@ -1387,11 +1387,9 @@ void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttr
|
||||
if (cut_connectors.empty())
|
||||
return;
|
||||
|
||||
indexed_triangle_set connector_mesh = get_connector_mesh(connector_attributes);
|
||||
|
||||
size_t connector_id = cut_id.connectors_cnt();
|
||||
for (const CutConnector& connector : cut_connectors) {
|
||||
TriangleMesh mesh = TriangleMesh(connector_mesh);
|
||||
TriangleMesh mesh = TriangleMesh(get_connector_mesh(connector.attribs));
|
||||
// Mesh will be centered when loading.
|
||||
ModelVolume* new_volume = add_volume(std::move(mesh), ModelVolumeType::NEGATIVE_VOLUME);
|
||||
|
||||
@ -1403,7 +1401,7 @@ void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttr
|
||||
Vec3d::Ones()
|
||||
));
|
||||
|
||||
new_volume->cut_info = { true, connector.radius_tolerance, connector.height_tolerance };
|
||||
new_volume->cut_info = { true, connector.attribs.type, connector.radius_tolerance, connector.height_tolerance };
|
||||
new_volume->name = name + "-" + std::to_string(++connector_id);
|
||||
}
|
||||
cut_id.increase_connectors_cnt(cut_connectors.size());
|
||||
@ -1541,13 +1539,13 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
||||
ModelVolume* vol = lower->add_volume(*volume);
|
||||
vol->set_transformation(volume_matrix);
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels))
|
||||
if (volume->cut_info.connector_type == CutConnectorType::Dowel)
|
||||
apply_tolerance(vol);
|
||||
else
|
||||
// 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)) {
|
||||
if (volume->cut_info.connector_type == CutConnectorType::Dowel) {
|
||||
// add one more solid part same as connector if this connector is a dowel
|
||||
ModelVolume* vol = dowels->add_volume(*volume);
|
||||
vol->set_type(ModelVolumeType::MODEL_PART);
|
||||
|
@ -219,48 +219,6 @@ private:
|
||||
friend class ModelObject;
|
||||
};
|
||||
|
||||
struct CutConnector
|
||||
{
|
||||
Vec3d pos;
|
||||
Vec3d rotation;
|
||||
float radius;
|
||||
float height;
|
||||
float radius_tolerance;// [0.f : 1.f]
|
||||
float height_tolerance;// [0.f : 1.f]
|
||||
bool failed = false;
|
||||
|
||||
CutConnector()
|
||||
: pos(Vec3d::Zero()), rotation(Vec3d::UnitZ()), radius(5.f), height(10.f), radius_tolerance(0.f), height_tolerance(0.1f)
|
||||
{}
|
||||
|
||||
CutConnector(Vec3d p, Vec3d rot, float r, float h, float rt, float ht, bool fl = false)
|
||||
: pos(p), rotation(rot), radius(r), height(h), radius_tolerance(rt), height_tolerance(ht), failed(fl)
|
||||
{}
|
||||
|
||||
CutConnector(const CutConnector& rhs) :
|
||||
CutConnector(rhs.pos, rhs.rotation, rhs.radius, rhs.height, rhs.radius_tolerance, rhs.height_tolerance, rhs.failed) {}
|
||||
|
||||
bool operator==(const CutConnector& sp) const;
|
||||
|
||||
bool operator!=(const CutConnector& sp) const { return !(sp == (*this)); }
|
||||
/*
|
||||
bool is_inside(const Vec3f& pt) const;
|
||||
|
||||
bool get_intersections(const Vec3f& s, const Vec3f& dir,
|
||||
std::array<std::pair<float, Vec3d>, 2>& out) const;
|
||||
|
||||
indexed_triangle_set to_mesh() const;
|
||||
*/
|
||||
template<class Archive> inline void serialize(Archive& ar)
|
||||
{
|
||||
ar(pos, rotation, radius, height, radius_tolerance, height_tolerance, failed);
|
||||
}
|
||||
|
||||
static constexpr size_t steps = 32;
|
||||
};
|
||||
|
||||
using CutConnectors = std::vector<CutConnector>;
|
||||
|
||||
enum class CutConnectorType : int {
|
||||
Plug
|
||||
, Dowel
|
||||
@ -283,8 +241,8 @@ enum class CutConnectorShape : int {
|
||||
struct CutConnectorAttributes
|
||||
{
|
||||
CutConnectorType type{ CutConnectorType::Plug };
|
||||
CutConnectorStyle style{ CutConnectorStyle::Prizm};
|
||||
CutConnectorShape shape{CutConnectorShape::Circle};
|
||||
CutConnectorStyle style{ CutConnectorStyle::Prizm };
|
||||
CutConnectorShape shape{ CutConnectorShape::Circle };
|
||||
|
||||
CutConnectorAttributes() {}
|
||||
|
||||
@ -294,8 +252,55 @@ struct CutConnectorAttributes
|
||||
|
||||
CutConnectorAttributes(const CutConnectorAttributes& rhs) :
|
||||
CutConnectorAttributes(rhs.type, rhs.style, rhs.shape) {}
|
||||
|
||||
bool operator==(const CutConnectorAttributes& other) const;
|
||||
|
||||
bool operator!=(const CutConnectorAttributes& other) const { return !(other == (*this)); }
|
||||
|
||||
bool operator<(const CutConnectorAttributes& other) const {
|
||||
return this->type < other.type ||
|
||||
(this->type == other.type && this->style < other.style) ||
|
||||
(this->type == other.type && this->style == other.style && this->shape < other.shape);
|
||||
}
|
||||
|
||||
template<class Archive> inline void serialize(Archive& ar) {
|
||||
ar(type, style, shape);
|
||||
}
|
||||
};
|
||||
|
||||
struct CutConnector
|
||||
{
|
||||
Vec3d pos;
|
||||
Vec3d rotation;
|
||||
float radius;
|
||||
float height;
|
||||
float radius_tolerance;// [0.f : 1.f]
|
||||
float height_tolerance;// [0.f : 1.f]
|
||||
CutConnectorAttributes attribs;
|
||||
|
||||
CutConnector()
|
||||
: pos(Vec3d::Zero()), rotation(Vec3d::UnitZ()), radius(5.f), height(10.f), radius_tolerance(0.f), height_tolerance(0.1f)
|
||||
{}
|
||||
|
||||
CutConnector(Vec3d p, Vec3d rot, float r, float h, float rt, float ht, CutConnectorAttributes attributes)
|
||||
: pos(p), rotation(rot), radius(r), height(h), radius_tolerance(rt), height_tolerance(ht), attribs(attributes)
|
||||
{}
|
||||
|
||||
CutConnector(const CutConnector& rhs) :
|
||||
CutConnector(rhs.pos, rhs.rotation, rhs.radius, rhs.height, rhs.radius_tolerance, rhs.height_tolerance, rhs.attribs) {}
|
||||
|
||||
bool operator==(const CutConnector& other) const;
|
||||
|
||||
bool operator!=(const CutConnector& other) const { return !(other == (*this)); }
|
||||
|
||||
template<class Archive> inline void serialize(Archive& ar) {
|
||||
ar(pos, rotation, radius, height, radius_tolerance, height_tolerance, attribs);
|
||||
}
|
||||
};
|
||||
|
||||
using CutConnectors = std::vector<CutConnector>;
|
||||
|
||||
|
||||
// Declared outside of ModelVolume, so it could be forward declared.
|
||||
enum class ModelVolumeType : int {
|
||||
INVALID = -1,
|
||||
@ -436,7 +441,7 @@ public:
|
||||
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);
|
||||
void apply_cut_connectors(const std::string& name);
|
||||
// invalidate cut state for this and related objects from the whole model
|
||||
void invalidate_cut();
|
||||
void synchronize_model_after_cut();
|
||||
@ -710,12 +715,14 @@ public:
|
||||
// It contains information about connetors
|
||||
struct CutInfo
|
||||
{
|
||||
bool is_connector {false};
|
||||
float radius_tolerance;// [0.f : 1.f]
|
||||
float height_tolerance;// [0.f : 1.f]
|
||||
bool is_connector{ false };
|
||||
CutConnectorType connector_type{ CutConnectorType::Plug };
|
||||
float radius_tolerance;// [0.f : 1.f]
|
||||
float height_tolerance;// [0.f : 1.f]
|
||||
|
||||
void discard() { is_connector = false; }
|
||||
} cut_info;
|
||||
};
|
||||
CutInfo cut_info;
|
||||
|
||||
// The triangular model.
|
||||
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
||||
|
@ -226,12 +226,15 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event)
|
||||
if (mouse_event.Moving() && !cut_line_processing())
|
||||
return false;
|
||||
|
||||
if (use_grabbers(mouse_event))
|
||||
return true;
|
||||
|
||||
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
|
||||
Vec2d mouse_pos = mouse_coord.cast<double>();
|
||||
|
||||
if (use_grabbers(mouse_event)) {
|
||||
if (m_hover_id >= m_connectors_group_id && mouse_event.LeftUp() && !mouse_event.ShiftDown())
|
||||
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pending_right_up = false;
|
||||
if (mouse_event.LeftDown()) {
|
||||
bool grabber_contains_mouse = (get_hover_id() != -1);
|
||||
@ -407,6 +410,9 @@ bool GLGizmoCut3D::render_combo(const std::string& label, const std::vector<std:
|
||||
bool is_changed = selection_idx != selection_out;
|
||||
selection_idx = selection_out;
|
||||
|
||||
if (is_changed)
|
||||
update_connector_shape();
|
||||
|
||||
return is_changed;
|
||||
}
|
||||
|
||||
@ -486,14 +492,16 @@ void GLGizmoCut3D::render_move_center_input(int axis)
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_connect_type_radio_button(CutConnectorType type)
|
||||
bool 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[size_t(type)], m_connector_type == type)) {
|
||||
m_connector_type = type;
|
||||
update_connector_shape();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_connect_mode_radio_button(CutConnectorMode mode)
|
||||
@ -1268,31 +1276,63 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
render_connect_mode_radio_button(CutConnectorMode::Auto);
|
||||
render_connect_mode_radio_button(CutConnectorMode::Manual);
|
||||
*/
|
||||
|
||||
if (m_selected_count == 1)
|
||||
for (size_t idx = 0; idx < m_selected.size(); idx++)
|
||||
if (m_selected[idx]) {
|
||||
auto& connector = connectors[idx];
|
||||
m_connector_depth_ratio = connector.height;
|
||||
m_connector_depth_ratio_tolerance = 100 * connector.height_tolerance;
|
||||
m_connector_size = 2. * connector.radius;
|
||||
m_connector_size_tolerance = 100 * connector.radius_tolerance;
|
||||
m_connector_type = connector.attribs.type;
|
||||
m_connector_style = size_t(connector.attribs.style);
|
||||
m_connector_shape_id = size_t(connector.attribs.shape);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
m_imgui->text(_L("Type"));
|
||||
render_connect_type_radio_button(CutConnectorType::Plug);
|
||||
render_connect_type_radio_button(CutConnectorType::Dowel);
|
||||
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
|
||||
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
|
||||
if (type_changed)
|
||||
for (size_t idx = 0; idx < m_selected.size() ; idx++)
|
||||
if (m_selected[idx])
|
||||
connectors[idx].attribs.type = CutConnectorType(m_connector_type);
|
||||
|
||||
if (render_combo(_u8L("Style"), m_connector_styles, m_connector_style))
|
||||
update_connector_shape();
|
||||
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
|
||||
update_connector_shape();
|
||||
for (size_t idx = 0; idx < m_selected.size() ; idx++)
|
||||
if (m_selected[idx])
|
||||
connectors[idx].attribs.style = CutConnectorStyle(m_connector_style) ;
|
||||
|
||||
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
|
||||
for (size_t idx = 0; idx < m_selected.size() ; idx++)
|
||||
if (m_selected[idx])
|
||||
connectors[idx].attribs.shape = CutConnectorShape(m_connector_shape_id);
|
||||
|
||||
if (render_slider_double_input(_u8L("Depth ratio"), m_connector_depth_ratio, m_connector_depth_ratio_tolerance))
|
||||
for (size_t idx = 0; idx < m_selected.size() ; idx++)
|
||||
if (m_selected[idx]) {
|
||||
auto& connector = connectors[idx];
|
||||
connector.height = float(m_connector_depth_ratio);
|
||||
connector.height_tolerance = 0.01f * m_connector_depth_ratio_tolerance;
|
||||
}
|
||||
|
||||
if (render_slider_double_input(_u8L("Depth ratio"), m_connector_depth_ratio, m_connector_depth_ratio_tolerance))
|
||||
for (auto& connector : connectors) {
|
||||
connector.height = float(m_connector_depth_ratio);
|
||||
connector.height_tolerance = 0.01f * m_connector_depth_ratio;
|
||||
}
|
||||
if (render_slider_double_input(_u8L("Size"), m_connector_size, m_connector_size_tolerance))
|
||||
for (auto& connector : connectors) {
|
||||
connector.radius = float(m_connector_size * 0.5);
|
||||
connector.radius_tolerance = 0.01f * m_connector_size_tolerance;
|
||||
}
|
||||
for (size_t idx = 0; idx < m_selected.size(); idx++)
|
||||
if (m_selected[idx]) {
|
||||
auto& connector = connectors[idx];
|
||||
connector.radius = float(m_connector_size * 0.5);
|
||||
connector.radius_tolerance = 0.01f * m_connector_size_tolerance;
|
||||
}
|
||||
|
||||
m_imgui->disabled_end();
|
||||
|
||||
if (m_imgui->button(_L("Confirm connectors"))) {
|
||||
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
|
||||
m_connectors_editing = false;
|
||||
std::fill(m_selected.begin(), m_selected.end(), false);
|
||||
m_selected_count = 0;
|
||||
}
|
||||
m_parent.request_extra_frame();
|
||||
}
|
||||
@ -1380,7 +1420,6 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
m_selected.resize(connectors.size(), false);
|
||||
}
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
@ -1388,19 +1427,8 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
shader->start_using();
|
||||
|
||||
ScopeGuard guard([shader]() { shader->stop_using(); });
|
||||
#else
|
||||
GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light");
|
||||
if (shader)
|
||||
shader->start_using();
|
||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#else
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift()));
|
||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
|
||||
ColorRGBA render_color;
|
||||
|
||||
@ -1417,13 +1445,12 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
|
||||
for (size_t i = 0; i < connectors.size(); ++i) {
|
||||
const CutConnector& connector = connectors[i];
|
||||
// const bool& point_selected = m_selected[i];
|
||||
|
||||
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)) {
|
||||
if (connector.attribs.type == CutConnectorType::Dowel &&
|
||||
connector.attribs.style == CutConnectorStyle::Prizm) {
|
||||
pos -= height * normal;
|
||||
height *= 2;
|
||||
}
|
||||
@ -1435,7 +1462,13 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
else {
|
||||
if (size_t(m_hover_id- m_connectors_group_id) == i)
|
||||
render_color = ColorRGBA::CYAN();
|
||||
else { // neither hover nor picking
|
||||
else if (m_selected[i])
|
||||
render_color = ColorRGBA::DARK_GRAY();
|
||||
else // neither hover nor picking
|
||||
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
|
||||
|
||||
// ! #ysFIXME rework get_volume_transformation
|
||||
if (0) { // else { // neither hover nor picking
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
++mesh_id;
|
||||
@ -1454,42 +1487,18 @@ void GLGizmoCut3D::render_connectors(bool picking)
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
m_connector_shape.set_color(render_color);
|
||||
m_shapes[connector.attribs].set_color(render_color);
|
||||
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(
|
||||
Vec3d(pos.x(), pos.y(), pos.z()),
|
||||
pos,
|
||||
Geometry::Transformation(m_rotation_m).get_rotation(),
|
||||
Vec3d(connector.radius, connector.radius, height),
|
||||
Vec3d::Ones()
|
||||
Vec3d(connector.radius, connector.radius, height)
|
||||
);
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
#else
|
||||
const_cast<GLModel*>(&m_connector_shape)->set_color(-1, render_color);
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
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));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
|
||||
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, height));
|
||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
|
||||
m_connector_shape.render();
|
||||
|
||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
glsafe(::glPopMatrix());
|
||||
#endif //!ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
m_shapes[connector.attribs].render();
|
||||
}
|
||||
|
||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
glsafe(::glPopMatrix());
|
||||
#endif //!ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::can_perform_cut() const
|
||||
@ -1535,9 +1544,10 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||
for (CutConnector& connector : mo->cut_connectors) {
|
||||
connector.rotation = rotation;
|
||||
|
||||
if (m_connector_type == CutConnectorType::Dowel) {
|
||||
if (m_connector_style == size_t(CutConnectorStyle::Prizm))
|
||||
if (connector.attribs.type == CutConnectorType::Dowel) {
|
||||
if (connector.attribs.style == CutConnectorStyle::Prizm)
|
||||
connector.height *= 2;
|
||||
create_dowels_as_separate_object = true;
|
||||
}
|
||||
else {
|
||||
// culculate shift of the connector center regarding to the position on the cut plane
|
||||
@ -1551,9 +1561,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||
connector.pos += norm * (0.5 * connector.height);
|
||||
}
|
||||
}
|
||||
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;
|
||||
mo->apply_cut_connectors(_u8L("Connector"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1623,15 +1631,15 @@ void GLGizmoCut3D::reset_connectors()
|
||||
|
||||
void GLGizmoCut3D::update_connector_shape()
|
||||
{
|
||||
if (m_connector_shape.is_initialized())
|
||||
m_connector_shape.reset();
|
||||
|
||||
const indexed_triangle_set its = ModelObject::get_connector_mesh({ m_connector_type, CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id) });
|
||||
m_connector_shape.init_from(its);
|
||||
CutConnectorAttributes attribs = { m_connector_type, CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id) };
|
||||
if (m_shapes.find(attribs) == m_shapes.end()) {
|
||||
const indexed_triangle_set its = ModelObject::get_connector_mesh(attribs);
|
||||
m_shapes[attribs].init_from(its);
|
||||
}
|
||||
|
||||
const indexed_triangle_set its = ModelObject::get_connector_mesh(attribs);
|
||||
m_connector_mesh.clear();
|
||||
m_connector_mesh = TriangleMesh(its);
|
||||
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::update_model_object() const
|
||||
@ -1709,14 +1717,9 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
|
||||
|
||||
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
|
||||
|
||||
// left down without selection rectangle - place connector on the cut plane:
|
||||
if (action == SLAGizmoEventType::LeftDown && /*!m_selection_rectangle.is_dragging() && */!shift_down && m_connectors_editing) {
|
||||
// If any point is in hover state, this should initiate its move - return control back to GLCanvas:
|
||||
if (m_hover_id != -1)
|
||||
return false;
|
||||
|
||||
// If there is some selection, don't add new point and deselect everything instead.
|
||||
if (m_selection_empty) {
|
||||
if (action == SLAGizmoEventType::LeftDown && !shift_down && m_connectors_editing) {
|
||||
// If there is no selection and no hovering, add new point
|
||||
if (m_hover_id == -1 && !control_down && !alt_down) {
|
||||
std::pair<Vec3d, Vec3d> pos_and_normal;
|
||||
if (unproject_on_cut_plane(mouse_position.cast<double>(), pos_and_normal)) {
|
||||
const Vec3d& hit = pos_and_normal.first;
|
||||
@ -1726,12 +1729,15 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
|
||||
|
||||
connectors.emplace_back(hit, Geometry::Transformation(m_rotation_m).get_rotation(),
|
||||
float(m_connector_size * 0.5), float(m_connector_depth_ratio),
|
||||
float(0.01f * m_connector_size_tolerance), float(0.01f * m_connector_depth_ratio_tolerance));
|
||||
float(0.01f * m_connector_size_tolerance), float(0.01f * m_connector_depth_ratio_tolerance),
|
||||
CutConnectorAttributes( CutConnectorType(m_connector_type),
|
||||
CutConnectorStyle(m_connector_style),
|
||||
CutConnectorShape(m_connector_shape_id)));
|
||||
update_model_object();
|
||||
m_selected.push_back(false);
|
||||
std::fill(m_selected.begin(), m_selected.end(), false);
|
||||
m_selected.push_back(true);
|
||||
assert(m_selected.size() == connectors.size());
|
||||
m_parent.set_as_dirty();
|
||||
m_wait_for_up_event = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1739,6 +1745,23 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (action == SLAGizmoEventType::LeftUp && !shift_down && m_connectors_editing) {
|
||||
if (m_hover_id >= m_connectors_group_id) {
|
||||
if (alt_down) {
|
||||
m_selected[m_hover_id - m_connectors_group_id] = false;
|
||||
--m_selected_count;
|
||||
}
|
||||
else {
|
||||
if (!control_down) {
|
||||
std::fill(m_selected.begin(), m_selected.end(), false);
|
||||
m_selected_count = 0;
|
||||
}
|
||||
m_selected[m_hover_id - m_connectors_group_id] = true;
|
||||
++m_selected_count;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (action == SLAGizmoEventType::RightDown && !shift_down && m_connectors_editing) {
|
||||
// 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)
|
||||
|
@ -12,6 +12,7 @@ namespace Slic3r {
|
||||
|
||||
enum class CutConnectorType : int;
|
||||
class ModelVolume;
|
||||
struct CutConnectorAttributes;
|
||||
|
||||
namespace GUI {
|
||||
class Selection;
|
||||
@ -44,7 +45,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
Transform3d m_start_dragging_m{ Transform3d::Identity() };
|
||||
double m_angle{ 0.0 };
|
||||
|
||||
GLModel m_connector_shape;
|
||||
std::map<CutConnectorAttributes, GLModel> m_shapes;
|
||||
TriangleMesh m_connector_mesh;
|
||||
// workaround for using of the clipping plane normal
|
||||
Vec3d m_clp_normal{ Vec3d::Ones() };
|
||||
@ -90,8 +91,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
bool force_update_clipper_on_render{false};
|
||||
|
||||
mutable std::vector<bool> m_selected; // which pins are currently selected
|
||||
bool m_selection_empty = true;
|
||||
bool m_wait_for_up_event = false;
|
||||
int m_selected_count{ 0 };
|
||||
|
||||
bool m_has_invalid_connector{ false };
|
||||
|
||||
@ -181,7 +181,7 @@ private:
|
||||
void render_move_center_input(int axis);
|
||||
void render_connect_mode_radio_button(CutConnectorMode mode);
|
||||
bool render_revert_button(const std::string& label);
|
||||
void render_connect_type_radio_button(CutConnectorType type);
|
||||
bool render_connect_type_radio_button(CutConnectorType type);
|
||||
Transform3d get_volume_transformation(const ModelVolume* volume) const;
|
||||
void render_connectors(bool picking);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user