From 099d59ad2755bb3b008bc8172c8c39107c4a1ae7 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 13 Jun 2018 13:14:17 +0200 Subject: Selection on gizmo overlay --- xs/src/slic3r/GUI/GLCanvas3D.cpp | 162 ++++++++++++++++++++++++++------------- xs/src/slic3r/GUI/GLCanvas3D.hpp | 15 ++-- 2 files changed, 116 insertions(+), 61 deletions(-) (limited to 'xs') diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 9ad7afeb8..e3db3af10 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -564,11 +564,14 @@ GLCanvas3D::Axes::Axes() { } -void GLCanvas3D::Axes::render() const +void GLCanvas3D::Axes::render(bool depth_test) const { ::glDisable(GL_LIGHTING); - // disable depth testing so that axes are not covered by ground - ::glDisable(GL_DEPTH_TEST); + if (depth_test) + ::glEnable(GL_DEPTH_TEST); + else + ::glDisable(GL_DEPTH_TEST); + ::glLineWidth(2.0f); ::glBegin(GL_LINES); // draw line for x axis @@ -582,7 +585,9 @@ void GLCanvas3D::Axes::render() const ::glEnd(); // draw line for Z axis // (re-enable depth test so that axis is correctly shown when objects are behind it) - ::glEnable(GL_DEPTH_TEST); + if (!depth_test) + ::glEnable(GL_DEPTH_TEST); + ::glBegin(GL_LINES); ::glColor3f(0.0f, 0.0f, 1.0f); ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y, (GLfloat)origin.z); @@ -841,21 +846,6 @@ float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas) -1000.0f; } -int GLCanvas3D::LayersEditing::get_first_selected_object_id(const GLVolumeCollection& volumes, unsigned int objects_count) -{ - for (const GLVolume* vol : volumes.volumes) - { - if ((vol != nullptr) && vol->selected) - { - int object_id = vol->select_group_id / 1000000; - // Objects with object_id >= 1000 have a specific meaning, for example the wipe tower proxy. - if (object_id < 10000) - return (object_id >= (int)objects_count) ? -1 : object_id; - } - } - return -1; -} - bool GLCanvas3D::LayersEditing::bar_rect_contains(const GLCanvas3D& canvas, float x, float y) { const Rect& rect = get_bar_rect_screen(canvas); @@ -1156,19 +1146,68 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Poin float top_y = 0.5f * (cnv_h - height); for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { - if ((it->second == nullptr) || (it->second->get_state() == GLGizmoBase::On)) + if (it->second == nullptr) continue; float tex_size = (float)it->second->get_textures_size(); float half_tex_size = 0.5f * tex_size; // we currently use circular icons for gizmo, so we check the radius - bool inside = length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size; - it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); + if (it->second->get_state() != GLGizmoBase::On) + { + bool inside = length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size; + it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); + } + top_y += (tex_size + OverlayGapY); + } +} + +void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos) +{ + if (!m_enabled) + return; + + float cnv_h = (float)canvas.get_canvas_size().get_height(); + float height = _get_total_overlay_height(); + float top_y = 0.5f * (cnv_h - height); + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if (it->second == nullptr) + continue; + + float tex_size = (float)it->second->get_textures_size(); + float half_tex_size = 0.5f * tex_size; + + // we currently use circular icons for gizmo, so we check the radius + if (length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size) + it->second->set_state((it->second->get_state() == GLGizmoBase::On) ? GLGizmoBase::Off : GLGizmoBase::On); + else + it->second->set_state(GLGizmoBase::Off); + top_y += (tex_size + OverlayGapY); } } +void GLCanvas3D::Gizmos::reset_all_states() +{ + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if (it->second != nullptr) + it->second->set_state(GLGizmoBase::Off); + } +} + +bool GLCanvas3D::Gizmos::contains_mouse() const +{ + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second != nullptr) && (it->second->get_state() == GLGizmoBase::Hover)) + return true; + } + + return false; +} + void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas) const { if (!m_enabled) @@ -1696,14 +1735,15 @@ void GLCanvas3D::render() if (is_custom_bed) { _render_bed(theta); - _render_axes(); + // disable depth testing so that axes are not covered by ground + _render_axes(false); } _render_objects(); // textured bed needs to be rendered after objects if (!is_custom_bed) { + _render_axes(true); _render_bed(theta); - _render_axes(); } _render_cutting_plane(); _render_warning_texture(); @@ -2439,13 +2479,13 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) return; // Performs layers editing updates, if enabled - if (is_layers_editing_enabled() && (m_print != nullptr)) + if (is_layers_editing_enabled()) { - int object_idx_selected = _get_layers_editing_first_selected_object_id((unsigned int)m_print->objects.size()); + int object_idx_selected = _get_first_selected_object_id(); if (object_idx_selected != -1) { // A volume is selected. Test, whether hovering over a layer thickness bar. - if (_bar_rect_contains((float)evt.GetX(), (float)evt.GetY())) + if (m_layers_editing.bar_rect_contains(*this, (float)evt.GetX(), (float)evt.GetY())) { // Adjust the width of the selection. m_layers_editing.band_width = std::max(std::min(m_layers_editing.band_width * (1.0f + 0.1f * (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta()), 10.0f), 1.5f); @@ -2485,8 +2525,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { Point pos(evt.GetX(), evt.GetY()); - int selected_object_idx = (is_layers_editing_enabled() && (m_print != nullptr)) ? _get_layers_editing_first_selected_object_id(m_print->objects.size()) : -1; - m_layers_editing.last_object_id = selected_object_idx; + int selected_object_idx = _get_first_selected_object_id(); + int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; + m_layers_editing.last_object_id = layer_editing_object_idx; + bool gizmos_contains_mouse = m_gizmos.contains_mouse(); if (evt.Entering()) { @@ -2506,25 +2548,30 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // on a volume or not. int volume_idx = m_hover_volume_id; m_layers_editing.state = LayersEditing::Unknown; - if ((selected_object_idx != -1) && _bar_rect_contains(pos.x, pos.y)) + if ((layer_editing_object_idx != -1) && m_layers_editing.bar_rect_contains(*this, pos.x, pos.y)) { // A volume is selected and the mouse is inside the layer thickness bar. // Start editing the layer height. m_layers_editing.state = LayersEditing::Editing; _perform_layer_editing_action(&evt); } - else if ((selected_object_idx != -1) && _reset_rect_contains(pos.x, pos.y)) + else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos.x, pos.y)) { if (evt.LeftDown()) { // A volume is selected and the mouse is inside the reset button. - m_print->get_object(selected_object_idx)->reset_layer_height_profile(); + m_print->get_object(layer_editing_object_idx)->reset_layer_height_profile(); // Index 2 means no editing, just wait for mouse up event. m_layers_editing.state = LayersEditing::Completed; m_dirty = true; } } + else if ((selected_object_idx != -1) && gizmos_contains_mouse) + { + m_gizmos.update_on_off_state(*this, m_mouse.position); + m_dirty = true; + } else { // Select volume in this 3D canvas. @@ -2586,7 +2633,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } } } - else if (evt.Dragging() && evt.LeftIsDown() && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.volume_idx != -1)) + else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.volume_idx != -1)) { m_mouse.dragging = true; @@ -2633,11 +2680,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } - else if (evt.Dragging()) + else if (evt.Dragging() && !gizmos_contains_mouse) { m_mouse.dragging = true; - if ((m_layers_editing.state != LayersEditing::Unknown) && (selected_object_idx != -1)) + if ((m_layers_editing.state != LayersEditing::Unknown) && (layer_editing_object_idx != -1)) { if (m_layers_editing.state == LayersEditing::Editing) _perform_layer_editing_action(&evt); @@ -2685,7 +2732,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_layers_editing.state = LayersEditing::Unknown; _stop_timer(); - if (selected_object_idx != -1) + if (layer_editing_object_idx != -1) m_on_model_update_callback.call(); } else if ((m_mouse.drag.volume_idx != -1) && m_mouse.dragging) @@ -3050,8 +3097,10 @@ void GLCanvas3D::_picking_pass() const } // updates gizmos overlay - if (!m_volumes.empty()) + if (_get_first_selected_object_id() != -1) m_gizmos.update_hover_state(*this, pos); + else + m_gizmos.reset_all_states(); } } @@ -3093,9 +3142,9 @@ void GLCanvas3D::_render_bed(float theta) const m_bed.render(theta); } -void GLCanvas3D::_render_axes() const +void GLCanvas3D::_render_axes(bool depth_test) const { - m_axes.render(); + m_axes.render(depth_test); } void GLCanvas3D::_render_objects() const @@ -3302,11 +3351,6 @@ float GLCanvas3D::_get_layers_editing_cursor_z_relative() const return m_layers_editing.get_cursor_z_relative(*this); } -int GLCanvas3D::_get_layers_editing_first_selected_object_id(unsigned int objects_count) const -{ - return m_layers_editing.get_first_selected_object_id(m_volumes, objects_count); -} - void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt) { int object_idx_selected = m_layers_editing.last_object_id; @@ -3355,16 +3399,6 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt) _start_timer(); } -bool GLCanvas3D::_bar_rect_contains(float x, float y) const -{ - return m_layers_editing.bar_rect_contains(*this, x, y); -} - -bool GLCanvas3D::_reset_rect_contains(float x, float y) const -{ - return m_layers_editing.reset_rect_contains(*this, x, y); -} - Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) { if (!set_current()) @@ -3401,6 +3435,26 @@ void GLCanvas3D::_stop_timer() m_timer->Stop(); } +int GLCanvas3D::_get_first_selected_object_id() const +{ + if (m_print != nullptr) + { + int objects_count = (int)m_print->objects.size(); + + for (const GLVolume* vol : m_volumes.volumes) + { + if ((vol != nullptr) && vol->selected) + { + int object_id = vol->select_group_id / 1000000; + // Objects with object_id >= 1000 have a specific meaning, for example the wipe tower proxy. + if (object_id < 10000) + return (object_id >= objects_count) ? -1 : object_id; + } + } + } + return -1; +} + static inline int hex_digit_to_int(const char c) { return diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 2852d82d1..738df637c 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -189,7 +189,7 @@ public: Axes(); - void render() const; + void render(bool depth_test) const; }; class CuttingPlane @@ -277,7 +277,6 @@ public: int get_shader_program_id() const; static float get_cursor_z_relative(const GLCanvas3D& canvas); - static int get_first_selected_object_id(const GLVolumeCollection& volumes, unsigned int objects_count); static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y); static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y); static Rect get_bar_rect_screen(const GLCanvas3D& canvas); @@ -355,6 +354,10 @@ public: void reset_selection(); void update_hover_state(const GLCanvas3D& canvas, const Pointf& mouse_pos); + void update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos); + void reset_all_states(); + + bool contains_mouse() const; void render(const GLCanvas3D& canvas) const; @@ -567,7 +570,7 @@ private: void _picking_pass() const; void _render_background() const; void _render_bed(float theta) const; - void _render_axes() const; + void _render_axes(bool depth_test) const; void _render_objects() const; void _render_cutting_plane() const; void _render_warning_texture() const; @@ -577,12 +580,8 @@ private: void _render_gizmo() const; float _get_layers_editing_cursor_z_relative() const; - int _get_layers_editing_first_selected_object_id(unsigned int objects_count) const; void _perform_layer_editing_action(wxMouseEvent* evt = nullptr); - bool _bar_rect_contains(float x, float y) const; - bool _reset_rect_contains(float x, float y) const; - // Convert the screen space coordinate to an object space coordinate. // If the Z screen space coordinate is not provided, a depth buffer value is substituted. Pointf3 _mouse_to_3d(const Point& mouse_pos, float* z = nullptr); @@ -590,6 +589,8 @@ private: void _start_timer(); void _stop_timer(); + int _get_first_selected_object_id() const; + // generates gcode extrusion paths geometry void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector& tool_colors); // generates gcode travel paths geometry -- cgit v1.2.3