diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c5b8bd436..08989089d 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1025,6 +1025,10 @@ sub increase { } else { $self->update; } + +#======================================================================================================================== + $self->selection_changed; # refresh info (size, volume etc.) +#======================================================================================================================== $self->schedule_background_process; } @@ -2223,17 +2227,30 @@ sub selection_changed { if ($self->{htoolbar}) { # On OSX or Linux $self->{htoolbar}->EnableTool($_, $have_sel) - for (TB_REMOVE, TB_MORE, TB_FEWER, TB_45CW, TB_45CCW, TB_SCALE, TB_SPLIT, TB_CUT, TB_SETTINGS); +#=================================================================================================================================================== + for (TB_REMOVE, TB_MORE, TB_45CW, TB_45CCW, TB_SCALE, TB_SPLIT, TB_CUT, TB_SETTINGS); +# for (TB_REMOVE, TB_MORE, TB_FEWER, TB_45CW, TB_45CCW, TB_SCALE, TB_SPLIT, TB_CUT, TB_SETTINGS); +#=================================================================================================================================================== #=================================================================================================================================================== $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, $layers_height_allowed); + + if ($have_sel) { + my $model_object = $self->{model}->objects->[$obj_idx]; + $self->{htoolbar}->EnableTool(TB_FEWER, $model_object->instances_count > 1); + } else { + $self->{htoolbar}->EnableTool(TB_FEWER, 0); + } #=================================================================================================================================================== } else { # On MSW my $method = $have_sel ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method - for grep $self->{"btn_$_"}, qw(remove increase decrease rotate45cw rotate45ccw changescale split cut settings); +#=================================================================================================================================================== + for grep $self->{"btn_$_"}, qw(remove increase rotate45cw rotate45ccw changescale split cut settings); +# for grep $self->{"btn_$_"}, qw(remove increase decrease rotate45cw rotate45ccw changescale split cut settings); +#=================================================================================================================================================== #=================================================================================================================================================== if ($layers_height_allowed) { @@ -2241,6 +2258,17 @@ sub selection_changed { } else { $self->{"btn_layer_editing"}->Disable; } + + if ($have_sel) { + my $model_object = $self->{model}->objects->[$obj_idx]; + if ($model_object->instances_count > 1) { + $self->{"btn_decrease"}->Enable; + } else { + $self->{"btn_decrease"}->Disable; + } + } else { + $self->{"btn_decrease"}->Disable; + } #=================================================================================================================================================== } @@ -2250,6 +2278,11 @@ sub selection_changed { } Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "layersediting", $layers_height_allowed); + + if ($have_sel) { + my $model_object = $self->{model}->objects->[$obj_idx]; + Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "fewer", $model_object->instances_count > 1); + } #=================================================================================================================================================== if ($self->{object_info_size}) { # have we already loaded the info pane? diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 7c8bf4665..414cad8e5 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1692,6 +1692,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) , m_timer(nullptr) +//################################################################################################################################### + , m_toolbar(*this) +//################################################################################################################################### , m_config(nullptr) , m_print(nullptr) , m_model(nullptr) @@ -2798,7 +2801,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_layers_editing.last_object_id = layer_editing_object_idx; bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position); //################################################################################################################################### - int toolbar_contains_mouse = m_toolbar.contains_mouse(*this, m_mouse.position); + int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position); //################################################################################################################################### if (evt.Entering()) @@ -2823,7 +2826,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (evt.LeftDClick() && (toolbar_contains_mouse != -1)) { m_toolbar_action_running = true; - m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this); + m_toolbar.do_action((unsigned int)toolbar_contains_mouse); } //################################################################################################################################### else if (evt.LeftDown() || evt.RightDown()) @@ -2868,7 +2871,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (toolbar_contains_mouse != -1) { m_toolbar_action_running = true; - m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this); + m_toolbar.do_action((unsigned int)toolbar_contains_mouse); } //################################################################################################################################### else @@ -2927,9 +2930,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } else if (evt.RightDown()) { - // if right clicking on volume, propagate event through callback - if (m_volumes.volumes[volume_idx]->hover) - m_on_right_click_callback.call(pos.x, pos.y); +//################################################################################################################################### + // forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while + // the context menu is already shown, ensuring it to disappear if the mouse is outside any volume + m_mouse.position = Pointf((coordf_t)pos.x, (coordf_t)pos.y); + render(); + if (m_hover_volume_id != -1) + { +//################################################################################################################################### + // if right clicking on volume, propagate event through callback (shows context menu) + if (m_volumes.volumes[volume_idx]->hover) + m_on_right_click_callback.call(pos.x, pos.y); +//################################################################################################################################### + } +//################################################################################################################################### } } } @@ -3128,7 +3142,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) _on_move(volume_idxs); } - else if (!m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled()) +//############################################################################################################################################################################# + else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled()) +// else if (!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 //################################################################################################################################### @@ -3780,7 +3797,7 @@ void GLCanvas3D::_picking_pass() const m_gizmos.reset_all_states(); //################################################################################################################################### - m_toolbar.update_hover_state(const_cast(*this), pos); + m_toolbar.update_hover_state(pos); //################################################################################################################################### } } @@ -4034,7 +4051,7 @@ void GLCanvas3D::_render_gizmo() const //################################################################################################################################### void GLCanvas3D::_render_toolbar() const { - m_toolbar.render(*this, m_mouse.position); + m_toolbar.render(m_mouse.position); } //################################################################################################################################### diff --git a/xs/src/slic3r/GUI/GLToolbar.cpp b/xs/src/slic3r/GUI/GLToolbar.cpp index e6e9eeac8..c425164a2 100644 --- a/xs/src/slic3r/GUI/GLToolbar.cpp +++ b/xs/src/slic3r/GUI/GLToolbar.cpp @@ -11,7 +11,7 @@ namespace Slic3r { namespace GUI { - GLToolbarItem::GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback) +GLToolbarItem::GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback) : m_type(type) , m_state(Disabled) , m_name(name) @@ -82,6 +82,16 @@ bool GLToolbarItem::is_enabled() const return m_state != Disabled; } +bool GLToolbarItem::is_hovered() const +{ + return (m_state == Hover) || (m_state == HoverPressed); +} + +bool GLToolbarItem::is_pressed() const +{ + return (m_state == Pressed) || (m_state == HoverPressed); +} + bool GLToolbarItem::is_toggable() const { return m_is_toggable; @@ -92,8 +102,9 @@ bool GLToolbarItem::is_separator() const return m_type == Separator; } -GLToolbar::GLToolbar() - : m_enabled(false) +GLToolbar::GLToolbar(GLCanvas3D& parent) + : m_parent(parent) + , m_enabled(false) , m_textures_scale(1.0f) , m_offset_y(5.0f) , m_gap_x(2.0f) @@ -156,7 +167,7 @@ void GLToolbar::enable_item(const std::string& name) { for (GLToolbarItem* item : m_items) { - if (item->get_name() == name) + if ((item->get_name() == name) && (item->get_state() == GLToolbarItem::Disabled)) { item->set_state(GLToolbarItem::Normal); return; @@ -181,18 +192,18 @@ bool GLToolbar::is_item_pressed(const std::string& name) const for (GLToolbarItem* item : m_items) { if (item->get_name() == name) - return (item->get_state() == GLToolbarItem::Pressed) || (item->get_state() == GLToolbarItem::HoverPressed); + return item->is_pressed(); } return false; } -void GLToolbar::update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos) +void GLToolbar::update_hover_state(const Pointf& mouse_pos) { if (!m_enabled) return; - float cnv_w = (float)canvas.get_canvas_size().get_width(); + float cnv_w = (float)m_parent.get_canvas_size().get_width(); float width = _get_total_width(); float left = 0.5f * (cnv_w - width); float top = m_offset_y; @@ -256,15 +267,15 @@ void GLToolbar::update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos) } } - canvas.set_tooltip(tooltip); + m_parent.set_tooltip(tooltip); } -int GLToolbar::contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const +int GLToolbar::contains_mouse(const Pointf& mouse_pos) const { if (!m_enabled) return -1; - float cnv_w = (float)canvas.get_canvas_size().get_width(); + float cnv_w = (float)m_parent.get_canvas_size().get_width(); float width = _get_total_width(); float left = 0.5f * (cnv_w - width); float top = m_offset_y; @@ -293,12 +304,12 @@ int GLToolbar::contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) return -1; } -void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& canvas) +void GLToolbar::do_action(unsigned int item_id) { if (item_id < (unsigned int)m_items.size()) { GLToolbarItem* item = m_items[item_id]; - if ((item != nullptr) && !item->is_separator() && item->is_enabled()) + if ((item != nullptr) && !item->is_separator() && item->is_hovered()) { if (item->is_toggable()) { @@ -308,26 +319,26 @@ void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& canvas) else if (state == GLToolbarItem::HoverPressed) item->set_state(GLToolbarItem::Hover); - canvas.render(); + m_parent.render(); item->do_action(); } else { item->set_state(GLToolbarItem::HoverPressed); - canvas.render(); + m_parent.render(); item->do_action(); if (item->get_state() != GLToolbarItem::Disabled) { - // the item may get disabled during the action, if not, set it to normal state + // the item may get disabled during the action, if not, set it back to hover state item->set_state(GLToolbarItem::Hover); - canvas.render(); + m_parent.render(); } } } } } -void GLToolbar::render(const GLCanvas3D& canvas, const Pointf& mouse_pos) const +void GLToolbar::render(const Pointf& mouse_pos) const { if (!m_enabled || m_items.empty()) return; @@ -337,9 +348,9 @@ void GLToolbar::render(const GLCanvas3D& canvas, const Pointf& mouse_pos) const ::glPushMatrix(); ::glLoadIdentity(); - float cnv_w = (float)canvas.get_canvas_size().get_width(); - float cnv_h = (float)canvas.get_canvas_size().get_height(); - float zoom = canvas.get_camera_zoom(); + float cnv_w = (float)m_parent.get_canvas_size().get_width(); + float cnv_h = (float)m_parent.get_canvas_size().get_height(); + float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; float width = _get_total_width(); diff --git a/xs/src/slic3r/GUI/GLToolbar.hpp b/xs/src/slic3r/GUI/GLToolbar.hpp index e5c8f9fb8..d157f2a3b 100644 --- a/xs/src/slic3r/GUI/GLToolbar.hpp +++ b/xs/src/slic3r/GUI/GLToolbar.hpp @@ -66,6 +66,9 @@ public: void do_action(); bool is_enabled() const; + bool is_hovered() const; + bool is_pressed() const; + bool is_toggable() const; bool is_separator() const; }; @@ -85,6 +88,7 @@ public: private: typedef std::vector ItemsList; + GLCanvas3D& m_parent; bool m_enabled; ItemsList m_items; @@ -94,7 +98,7 @@ private: float m_separator_x; public: - GLToolbar(); + explicit GLToolbar(GLCanvas3D& parent); bool is_enabled() const; void set_enabled(bool enable); @@ -112,14 +116,14 @@ public: bool is_item_pressed(const std::string& name) const; - void update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos); + void update_hover_state(const Pointf& mouse_pos); // returns the id of the item under the given mouse position or -1 if none - int contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; + int contains_mouse(const Pointf& mouse_pos) const; - void do_action(unsigned int item_id, GLCanvas3D& canvas); + void do_action(unsigned int item_id); - void render(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; + void render(const Pointf& mouse_pos) const; private: float _get_total_width() const;