SLA gizmo improvements

- point can be selected
- selection can be deleted, head diameter changed
- dragging of objects is not allowed with the gizmo being on
- added a modal dialog when automatic support generator is triggered
This commit is contained in:
Lukas Matena 2019-02-11 16:29:03 +01:00
parent 0453caf266
commit ac8f9ab3dc
5 changed files with 195 additions and 140 deletions

View file

@ -253,7 +253,7 @@ void SLAAutoSupports::uniformly_cover(const ExPolygon& island, Structure& struct
} }
for (const Vec3d& p : island_new_points) { for (const Vec3d& p : island_new_points) {
m_output.emplace_back(float(p(0)), float(p(1)), structure.height, 0.4f, is_new_island); m_output.emplace_back(float(p(0)), float(p(1)), structure.height, 0.2f, is_new_island);
structure.supports_force += m_config.support_force; structure.supports_force += m_config.support_force;
} }
} }

View file

@ -3430,24 +3430,18 @@ void GLCanvas3D::Gizmos::set_sla_support_data(ModelObject* model_object, const G
reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, selection); reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, selection);
} }
void GLCanvas3D::Gizmos::mouse_event(int action, const Vec2d& mouse_position, bool shift_down)
// Returns true if the gizmo used the event to do something, false otherwise.
bool GLCanvas3D::Gizmos::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
{ {
if (!m_enabled) if (!m_enabled)
return; return false;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end()) if (it != m_gizmos.end())
reinterpret_cast<GLGizmoSlaSupports*>(it->second)->mouse_event(action, mouse_position, shift_down); return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->mouse_event(action, mouse_position, shift_down);
}
void GLCanvas3D::Gizmos::delete_current_grabber(bool delete_all) return false;
{
if (!m_enabled)
return;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end())
reinterpret_cast<GLGizmoSlaSupports*>(it->second)->delete_current_point(delete_all);
} }
void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selection) const void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selection) const
@ -5185,8 +5179,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case 'a': case 'a':
case 'A': case 'A':
case WXK_CONTROL_A: case WXK_CONTROL_A:
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) // Sla gizmo selects all support points if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::SelectAll)) // Sla gizmo selects all support points
m_gizmos.mouse_event(5); m_dirty = true;
else else
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL)); post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
break; break;
@ -5210,7 +5204,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */ #else /* __APPLE__ */
case WXK_DELETE: case WXK_DELETE:
#endif /* __APPLE__ */ #endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::Delete))
m_dirty = true;
else
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
break;
case '0': { select_view("iso"); break; } case '0': { select_view("iso"); break; }
case '1': { select_view("top"); break; } case '1': { select_view("top"); break; }
case '2': { select_view("bottom"); break; } case '2': { select_view("bottom"); break; }
@ -5252,11 +5251,9 @@ void GLCanvas3D::on_key_up(wxKeyEvent& evt)
// see include/wx/defs.h enum wxKeyCode // see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode(); int keyCode = evt.GetKeyCode();
// shift has been just released - SLA gizmo might want to close rectangular selection: // shift has been just released - SLA gizmo might want to close rectangular selection.
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT) { if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp))
m_gizmos.mouse_event(2);
m_dirty = true; m_dirty = true;
}
} }
void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
@ -5399,25 +5396,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
} }
#if !ENABLE_IMGUI
else if ((m_gizmos.get_current_type() == Gizmos::SlaSupports) && gizmo_reset_rect_contains(*this, pos(0), pos(1)))
{
if (evt.LeftDown())
{
m_gizmos.delete_current_grabber(true);
m_dirty = true;
}
}
#endif // not ENABLE_IMGUI
else if (!m_selection.is_empty() && gizmos_overlay_contains_mouse) else if (!m_selection.is_empty() && gizmos_overlay_contains_mouse)
{ {
m_gizmos.update_on_off_state(*this, m_mouse.position, m_selection); m_gizmos.update_on_off_state(*this, m_mouse.position, m_selection);
_update_gizmos_data(); _update_gizmos_data();
m_dirty = true; m_dirty = true;
} }
else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown()) // inform the gizmo about the event (rectangular selection init) else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
{ {
m_gizmos.mouse_event(1, Vec2d(pos(0), pos(1)), evt.ShiftDown()); // the gizmo got the event and took some action, there is no need to do anything more
} }
else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse())
{ {
@ -5434,10 +5421,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse() && evt.RightDown()) { /*else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse() && evt.RightDown()) {
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) if (m_gizmos.get_current_type() == Gizmos::SlaSupports)
m_gizmos.delete_current_grabber(); m_gizmos.delete_current_grabber();
} }*/
else if (view_toolbar_contains_mouse != -1) else if (view_toolbar_contains_mouse != -1)
{ {
if (m_view_toolbar != nullptr) if (m_view_toolbar != nullptr)
@ -5542,7 +5529,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
} }
else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.move_volume_idx != -1)) else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown)
&& (m_mouse.drag.move_volume_idx != -1) && m_gizmos.get_current_type() != Gizmos::SlaSupports /* don't allow dragging objects with the Sla gizmo on */)
{ {
#if ENABLE_MOVE_MIN_THRESHOLD #if ENABLE_MOVE_MIN_THRESHOLD
if (!m_mouse.drag.move_requires_threshold) if (!m_mouse.drag.move_requires_threshold)
@ -5602,9 +5590,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
else if (evt.Dragging() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown()) else if (evt.Dragging() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::Dragging, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
{ {
m_gizmos.mouse_event(3, Vec2d(pos(0), pos(1)), evt.ShiftDown()); // the gizmo got the event and took some action, no need to do anything more here
m_dirty = true; m_dirty = true;
} }
else if (evt.Dragging() && !gizmos_overlay_contains_mouse) else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
@ -5662,6 +5650,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
_stop_timer(); _stop_timer();
m_layers_editing.accept_changes(*this); m_layers_editing.accept_changes(*this);
} }
else if (evt.LeftUp() && m_gizmos.get_current_type() == Gizmos::SlaSupports && !m_gizmos.is_dragging()
&& !m_mouse.dragging && m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
{
// the gizmo got the event and took some action, no need to do anything more
}
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging) else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
{ {
m_regenerate_volumes = false; m_regenerate_volumes = false;
@ -5671,16 +5664,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// of the scene with the background processing data should be performed. // of the scene with the background processing data should be performed.
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
} }
else if (evt.LeftUp() && m_gizmos.get_current_type() == Gizmos::SlaSupports/* && m_hover_volume_id != -1*/) else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
&& !is_layers_editing_enabled() && m_gizmos.get_current_type() != Gizmos::SlaSupports)
{ {
int id = m_selection.get_object_idx(); // SLA gizmo cannot be deselected by clicking in canvas area to avoid inadvertent unselection and losing manual changes
if ((id != -1) && (m_model != nullptr)) {
m_gizmos.mouse_event(2, Vec2d(pos(0), pos(1)), evt.ShiftDown());
}
}
else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled())
{
// deselect and propagate event through callback // deselect and propagate event through callback
if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event) if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
{ {
@ -5713,10 +5701,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
do_rotate(); do_rotate();
break; break;
} }
case Gizmos::SlaSupports:
// End of mouse dragging, update the SLAPrint/SLAPrintObjects with the new support points.
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
break;
default: default:
break; break;
} }

View file

@ -132,6 +132,17 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
// this describes events being passed from GLCanvas3D to SlaSupport gizmo
enum class SLAGizmoEventType {
LeftDown = 1,
LeftUp,
Dragging,
Delete,
SelectAll,
ShiftUp
};
class GLCanvas3D class GLCanvas3D
{ {
struct GCodePreviewVolumeIndex struct GCodePreviewVolumeIndex
@ -789,7 +800,7 @@ private:
void set_flattening_data(const ModelObject* model_object); void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
void mouse_event(int action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false); bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
void delete_current_grabber(bool delete_all = false); void delete_current_grabber(bool delete_all = false);
void render_current_gizmo(const Selection& selection) const; void render_current_gizmo(const Selection& selection) const;

View file

@ -1795,8 +1795,9 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
if (po->model_object()->id() == model_object->id()) { if (po->model_object()->id() == model_object->id()) {
const Eigen::MatrixXd& points = po->get_support_points(); const Eigen::MatrixXd& points = po->get_support_points();
for (unsigned int i=0; i<points.rows();++i) for (unsigned int i=0; i<points.rows();++i)
m_editing_mode_cache.emplace_back(po->trafo().inverse().cast<float>() * Vec3f(points(i,0), points(i,1), points(i,2)), m_editing_mode_cache.push_back(std::make_pair(sla::SupportPoint(po->trafo().inverse().cast<float>() * Vec3f(points(i,0), points(i,1), points(i,2)),
points(i, 3), points(i, 4)); points(i, 3), points(i, 4)),
false));
break; break;
} }
} }
@ -1895,7 +1896,8 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
float render_color[3]; float render_color[3];
for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i) for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i)
{ {
const Vec3f& point_pos = m_editing_mode_cache[i].pos; const Vec3f& point_pos = m_editing_mode_cache[i].first.pos;
const bool point_selected = m_editing_mode_cache[i].second;
// first precalculate the grabber position in world coordinates, so that the grabber // first precalculate the grabber position in world coordinates, so that the grabber
// is not scaled with the object (as it would be if rendered with current gl matrix). // is not scaled with the object (as it would be if rendered with current gl matrix).
Eigen::Matrix<GLfloat, 4, 4, Eigen::DontAlign> glmatrix; Eigen::Matrix<GLfloat, 4, 4, Eigen::DontAlign> glmatrix;
@ -1919,11 +1921,11 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
render_color[2] = picking_color_component(i); render_color[2] = picking_color_component(i);
} }
else { // normal rendering else { // normal rendering
bool supports_new_island = m_lock_unique_islands && m_editing_mode_cache[i].is_new_island; bool supports_new_island = m_lock_unique_islands && m_editing_mode_cache[i].first.is_new_island;
if (m_editing_mode) { if (m_editing_mode) {
render_color[0] = supports_new_island ? 0.f : 1.f; render_color[0] = point_selected ? 0.f : (supports_new_island ? 0.f : 1.f);
render_color[1] = 0.f; render_color[1] = point_selected ? 1.f : 0.f;
render_color[2] = supports_new_island ? 1.f : 0.f; render_color[2] = point_selected ? 0.f : (supports_new_island ? 1.f : 0.f);
} }
else else
for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f; for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f;
@ -1934,7 +1936,7 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
::glPushMatrix(); ::glPushMatrix();
::glLoadIdentity(); ::glLoadIdentity();
::glTranslated(grabber_world_position(0), grabber_world_position(1), grabber_world_position(2) + z_shift); ::glTranslated(grabber_world_position(0), grabber_world_position(1), grabber_world_position(2) + z_shift);
::gluSphere(m_quadric, m_editing_mode_cache[i].head_front_radius, 64, 36); ::gluSphere(m_quadric, m_editing_mode_cache[i].first.head_front_radius, 64, 36);
::glPopMatrix(); ::glPopMatrix();
} }
@ -1982,7 +1984,9 @@ void GLGizmoSlaSupports::update_mesh()
m_AABB.init(m_V, m_F); m_AABB.init(m_V, m_F);
// we'll now reload support points (selection might have changed): // we'll now reload support points (selection might have changed):
m_editing_mode_cache = m_model_object->sla_support_points; m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.push_back(std::make_pair(point, false));
} }
Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
@ -2025,48 +2029,74 @@ Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
return bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)); return bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2));
} }
void GLGizmoSlaSupports::mouse_event(int action, const Vec2d& mouse_position, bool shift_down) // Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
// concludes that the event was not intended for it, it should return false.
bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
{ {
if (!m_editing_mode) if (!m_editing_mode)
return; return false;
// left down - show the selection rectangle: // left down - show the selection rectangle:
if (action == 1 && shift_down) { if (action == SLAGizmoEventType::LeftDown && shift_down) {
if (m_hover_id == -1) {
m_selection_rectangle_active = true; m_selection_rectangle_active = true;
m_selection_rectangle_start_corner = mouse_position; m_selection_rectangle_start_corner = mouse_position;
m_selection_rectangle_end_corner = mouse_position; m_selection_rectangle_end_corner = mouse_position;
m_canvas_width = m_parent.get_canvas_size().get_width(); m_canvas_width = m_parent.get_canvas_size().get_width();
m_canvas_height = m_parent.get_canvas_size().get_height(); m_canvas_height = m_parent.get_canvas_size().get_height();
} }
else
m_editing_mode_cache[m_hover_id].second = true;
return true;
}
// dragging the selection rectangle: // dragging the selection rectangle:
if (action == 3 && m_selection_rectangle_active) if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) {
m_selection_rectangle_end_corner = mouse_position; m_selection_rectangle_end_corner = mouse_position;
return true;
}
// mouse up without selection rectangle - place point on the mesh: // mouse up without selection rectangle - place point on the mesh:
if (action == 2 && !m_selection_rectangle_active) { if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) {
if (m_ignore_up_event) {
m_ignore_up_event = false;
return false;
}
int instance_id = m_parent.get_selection().get_instance_idx(); int instance_id = m_parent.get_selection().get_instance_idx();
if (m_old_instance_id != instance_id) if (m_old_instance_id != instance_id)
{ {
bool something_selected = (m_old_instance_id != -1); bool something_selected = (m_old_instance_id != -1);
m_old_instance_id = instance_id; m_old_instance_id = instance_id;
if (something_selected) if (something_selected)
return; return false;
} }
if (instance_id == -1) if (instance_id == -1)
return; return false;
// Regardless of whether the user clicked the object or not, we will unselect all points:
for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i)
m_editing_mode_cache[i].second = false;
Vec3f new_pos; Vec3f new_pos;
try { try {
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case
m_editing_mode_cache.emplace_back(std::make_pair(sla::SupportPoint(new_pos, m_new_point_head_diameter/2.f, false), true));
} }
catch (...) { return; } catch (...) { // not clicked on object
return false; // GLCanvas3D might want to deselect the gizmo
m_editing_mode_cache.emplace_back(new_pos, m_new_point_head_diameter, false); }
return true;
} }
// left up with selection rectangle - select points inside the rectangle: // left up with selection rectangle - select points inside the rectangle:
if (action == 2 && m_selection_rectangle_active) { if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp)
&& m_selection_rectangle_active) {
if (action == SLAGizmoEventType::ShiftUp)
m_ignore_up_event = true;
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix(); const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
GLint viewport[4]; GLint viewport[4];
::glGetIntegerv(GL_VIEWPORT, viewport); ::glGetIntegerv(GL_VIEWPORT, viewport);
@ -2082,68 +2112,61 @@ void GLGizmoSlaSupports::mouse_event(int action, const Vec2d& mouse_position, bo
// bounding box created from the rectangle corners - will take care of order of the corners // bounding box created from the rectangle corners - will take care of order of the corners
BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast<int>()), Point(m_selection_rectangle_end_corner.cast<int>())}); BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast<int>()), Point(m_selection_rectangle_end_corner.cast<int>())});
for (sla::SupportPoint& support_point : m_editing_mode_cache) { for (std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache) {
const sla::SupportPoint& support_point = point_and_selection.first;
Vec3f pos = instance_matrix.cast<float>() * support_point.pos; Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
pos(2) += z_offset; pos(2) += z_offset;
GLdouble out_x, out_y, out_z; GLdouble out_x, out_y, out_z;
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z); ::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
out_y = m_canvas_height - out_y; out_y = m_canvas_height - out_y;
/*GLfloat depth_comp;
::glReadPixels( out_x, out_y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_comp);
if (depth_comp > out_z + EPSILON) // the point is obscured by something else
continue;*/
if (rectangle.contains(Point(out_x, out_y))) if (rectangle.contains(Point(out_x, out_y)))
support_point.head_front_radius = 1.f; point_and_selection.second = true;
} }
m_selection_rectangle_active = false; m_selection_rectangle_active = false;
return true;
} }
if (action == 4) { if (action == SLAGizmoEventType::Delete) {
// shift has been released // delete key pressed
delete_selected_points();
return true;
} }
if (action == 5) { if (action == SLAGizmoEventType::SelectAll) {
// ctrl+A : select all for (auto& point_and_selection : m_editing_mode_cache)
std::cout << "select all..." << std::endl; point_and_selection.second = true;
return true;
} }
return false;
} }
void GLGizmoSlaSupports::delete_current_point(bool delete_all) void GLGizmoSlaSupports::delete_selected_points()
{ {
if (!m_editing_mode && !delete_all) if (!m_editing_mode)
return; return;
if (delete_all) { for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
m_editing_mode_cache.clear(); if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands))
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
// This should trigger the support generation // This should trigger the support generation
// wxGetApp().plater()->reslice(); // wxGetApp().plater()->reslice();
} }
else
if (m_hover_id != -1) {
if (!m_editing_mode_cache[m_hover_id].is_new_island || !m_lock_unique_islands) {
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + m_hover_id);
m_hover_id = -1;
// This should trigger the support generation
// wxGetApp().plater()->reslice();
}
}
//m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{ {
if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].is_new_island || !m_lock_unique_islands)) { if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].first.is_new_island || !m_lock_unique_islands)) {
Vec3f new_pos; Vec3f new_pos;
try { try {
new_pos = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); new_pos = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1)));
} }
catch (...) { return; } catch (...) { return; }
m_editing_mode_cache[m_hover_id].pos = new_pos; m_editing_mode_cache[m_hover_id].first.pos = new_pos;
m_editing_mode_cache[m_hover_id].is_new_island = false; m_editing_mode_cache[m_hover_id].first.is_new_island = false;
// Do not update immediately, wait until the mouse is released. // Do not update immediately, wait until the mouse is released.
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
@ -2193,29 +2216,13 @@ RENDER_AGAIN:
ImGui::PushItemWidth(100.0f); ImGui::PushItemWidth(100.0f);
/*bool force_refresh = m_editing_mode;
if (m_imgui->radio_button(_(L("Automatic")), !m_editing_mode))
m_editing_mode = false;
ImGui::SameLine();
if (m_imgui->radio_button(_(L("Manual")), m_editing_mode))
m_editing_mode = true;
force_refresh = force_refresh != m_editing_mode;
if (force_refresh) { // mode has just changed!
if (m_editing_mode)
m_editing_mode_cache = m_model_object->sla_support_points;
else
m_model_object->sla_support_points = m_editing_mode_cache;
}
*/
bool force_refresh = false; bool force_refresh = false;
bool remove_all_points = false; bool remove_selected = false;
bool old_editing_state = m_editing_mode; bool old_editing_state = m_editing_mode;
if (m_editing_mode) { if (m_editing_mode) {
m_imgui->text(_(L("Left mouse click - add point"))); m_imgui->text(_(L("Left mouse click - add point")));
m_imgui->text(_(L("Right mouse click - remove point"))); m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)")));
m_imgui->text(" "); // vertical gap m_imgui->text(" "); // vertical gap
std::vector<wxString> options = {"0.2", "0.4", "0.6", "0.8", "1.0"}; std::vector<wxString> options = {"0.2", "0.4", "0.6", "0.8", "1.0"};
@ -2223,28 +2230,38 @@ RENDER_AGAIN:
ss << std::setprecision(1) << m_new_point_head_diameter; ss << std::setprecision(1) << m_new_point_head_diameter;
wxString str = ss.str(); wxString str = ss.str();
m_imgui->combo(_(L("Head diameter")), options, str); m_imgui->combo(_(L("Head diameter")), options, str);
force_refresh |= std::abs(atof(str) - m_new_point_head_diameter) > 0.001; float current_number = atof(str);
m_new_point_head_diameter = atof(str); if (std::abs(current_number - m_new_point_head_diameter) > 0.001) {
force_refresh = true;
m_new_point_head_diameter = current_number;
for (auto& point_and_selection : m_editing_mode_cache)
if (point_and_selection.second)
point_and_selection.first.head_front_radius = current_number / 2.f;
}
bool changed = m_lock_unique_islands; bool changed = m_lock_unique_islands;
m_imgui->checkbox(_(L("Lock supports under new islands")), m_lock_unique_islands); m_imgui->checkbox(_(L("Lock supports under new islands")), m_lock_unique_islands);
force_refresh |= changed != m_lock_unique_islands; force_refresh |= changed != m_lock_unique_islands;
remove_all_points = m_imgui->button(_(L("Remove all points")) + (m_model_object == nullptr ? "" : " (" + std::to_string(m_editing_mode_cache.size())+")")); remove_selected = m_imgui->button(_(L("Remove selected points")));
m_imgui->text(" "); // vertical gap m_imgui->text(" "); // vertical gap
bool apply_changes = m_imgui->button(_(L("Apply changes"))); bool apply_changes = m_imgui->button(_(L("Apply changes")));
if (apply_changes) { if (apply_changes) {
m_model_object->sla_support_points = m_editing_mode_cache; m_model_object->sla_support_points.clear();
for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache)
m_model_object->sla_support_points.push_back(point_and_selection.first);
m_editing_mode = false; m_editing_mode = false;
force_refresh = true; force_refresh = true;
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
ImGui::SameLine(); ImGui::SameLine();
bool discard_changes = m_imgui->button(_(L("Cancel"))); bool discard_changes = m_imgui->button(_(L("Discard changes")));
if (discard_changes) { if (discard_changes) {
m_editing_mode_cache = m_model_object->sla_support_points; m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.push_back(std::make_pair(point, false));
m_editing_mode = false; m_editing_mode = false;
force_refresh = true; force_refresh = true;
} }
@ -2258,16 +2275,45 @@ RENDER_AGAIN:
m_imgui->text(""); m_imgui->text("");
bool generate =m_imgui->button(_(L("Auto-generate points"))); bool generate =m_imgui->button(_(L("Auto-generate points")));
force_refresh |= generate;
if (generate) { if (generate) {
ImGui::OpenPopup(_(L("Warning")));
m_show_modal = true;
force_refresh = true;
}
if (m_show_modal) {
if (ImGui::BeginPopupModal(_(L("Warning")), &m_show_modal/*, ImGuiWindowFlags_NoDecoration*/))
{
m_imgui->text(_(L("This will erase all your manual changes.")));
if (m_imgui->button(_(L("Continue"))))
{
ImGui::CloseCurrentPopup();
m_show_modal = false;
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
m_editing_mode_cache.clear(); m_editing_mode_cache.clear();
wxGetApp().plater()->reslice(); wxGetApp().plater()->reslice();
} }
ImGui::SameLine();
if (m_imgui->button(_(L("Cancel")))) {
ImGui::CloseCurrentPopup();
m_show_modal = false;
}
ImGui::EndPopup();
}
if (!m_show_modal)
force_refresh = true;
}
ImGui::SameLine(); ImGui::SameLine();
bool editing_clicked = m_imgui->button("Editing"); bool editing_clicked = m_imgui->button("Editing");
if (editing_clicked) { if (editing_clicked) {
m_editing_mode_cache = m_model_object->sla_support_points; m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.push_back(std::make_pair(point, false));
m_editing_mode = true; m_editing_mode = true;
} }
} }
@ -2280,10 +2326,10 @@ RENDER_AGAIN:
} }
if (remove_all_points) { if (remove_selected) {
force_refresh = false; force_refresh = false;
m_parent.reload_scene(true); m_parent.reload_scene(true);
delete_current_point(true); delete_selected_points();
if (first_run) { if (first_run) {
first_run = false; first_run = false;
goto RENDER_AGAIN; goto RENDER_AGAIN;
@ -2324,7 +2370,18 @@ void GLGizmoSlaSupports::on_set_state()
if (m_state == Off) { if (m_state == Off) {
m_parent.toggle_model_objects_visibility(true); m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; m_editing_mode = false;
if (m_show_modal) {
m_show_modal = false;
on_render_input_window(0,0,m_parent.get_selection()); // this is necessary to allow ImGui to terminate the modal dialog correctly
} }
}
}
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1)
for (unsigned int i=0;i<m_editing_mode_cache.size();++i)
m_editing_mode_cache[i].second = ((int)i == m_hover_id);
} }

View file

@ -464,8 +464,8 @@ public:
explicit GLGizmoSlaSupports(GLCanvas3D& parent); explicit GLGizmoSlaSupports(GLCanvas3D& parent);
virtual ~GLGizmoSlaSupports(); virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
void mouse_event(int action, const Vec2d& mouse_position, bool shift_down); bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_current_point(bool delete_all); void delete_selected_points();
private: private:
bool on_init(); bool on_init();
@ -487,16 +487,19 @@ private:
bool m_lock_unique_islands = false; bool m_lock_unique_islands = false;
bool m_editing_mode = false; bool m_editing_mode = false;
float m_new_point_head_diameter = 0.4f; float m_new_point_head_diameter = 0.4f;
std::vector<sla::SupportPoint> m_editing_mode_cache; std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected
bool m_selection_rectangle_active = false; bool m_selection_rectangle_active = false;
Vec2d m_selection_rectangle_start_corner; Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner; Vec2d m_selection_rectangle_end_corner;
bool m_ignore_up_event = false;
bool m_show_modal = false;
int m_canvas_width; int m_canvas_width;
int m_canvas_height; int m_canvas_height;
protected: protected:
void on_set_state() override; void on_set_state() override;
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
#if ENABLE_IMGUI #if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) override; virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) override;