From c751d6327db9da594c1f96f27d7df96cf7b5df6a Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Fri, 10 Dec 2021 09:09:53 +0100 Subject: [PATCH] Separate GizmoManager on_move into gizmo itself --- src/slic3r/GUI/GLCanvas3D.cpp | 9 - src/slic3r/GUI/GLCanvas3D.hpp | 1 - src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 80 +++- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 14 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 9 +- src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 45 +- src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp | 26 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 43 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 26 +- src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 25 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 101 +++++ src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 12 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 45 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 25 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 46 +- src/slic3r/GUI/Gizmos/GLGizmoScale.hpp | 12 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 58 ++- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 435 ++++++------------- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 38 +- 22 files changed, 614 insertions(+), 469 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 481f7d34ce..5f96906a3a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3600,15 +3600,6 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type) m_dirty = true; } -void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_type) -{ - if (!snapshot_type.empty()) - wxGetApp().plater()->take_snapshot(_(snapshot_type)); - - m_selection.flattening_rotate(normal); - do_rotate(""); // avoid taking another snapshot -} - void GLCanvas3D::do_mirror(const std::string& snapshot_type) { if (m_model == nullptr) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 605d75ddd2..74c61fbc6b 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -759,7 +759,6 @@ public: void do_move(const std::string& snapshot_type); void do_rotate(const std::string& snapshot_type); void do_scale(const std::string& snapshot_type); - void do_flatten(const Vec3d& normal, const std::string& snapshot_type); void do_mirror(const std::string& snapshot_type); void update_gizmos_on_off_state(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 393be1a4e8..ed3fb326d4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -5,6 +5,8 @@ #include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" + // TODO: Display tooltips quicker on Linux namespace Slic3r { @@ -97,11 +99,15 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u void GLGizmoBase::set_hover_id(int id) { - if (m_grabbers.empty() || (id < (int)m_grabbers.size())) - { - m_hover_id = id; - on_set_hover_id(); - } + // do not change hover id during dragging + if (m_dragging) return; + + // allow empty grabbers when not using grabbers but use hover_id - flatten, rotate + if (!m_grabbers.empty() && id >= (int) m_grabbers.size()) + return; + + m_hover_id = id; + on_set_hover_id(); } void GLGizmoBase::set_highlight_color(const std::array& color) @@ -149,18 +155,12 @@ void GLGizmoBase::stop_dragging() on_stop_dragging(); } -void GLGizmoBase::update(const UpdateData& data) -{ - if (m_hover_id != -1) - on_update(data); -} - bool GLGizmoBase::update_items_state() { bool res = m_dirty; m_dirty = false; return res; -}; +} std::array GLGizmoBase::picking_color_component(unsigned int id) const { @@ -212,6 +212,62 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const } } +// help function to process grabbers +// call start_dragging, stop_dragging, on_dragging +bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) { + if (mouse_event.Moving()) { + assert(!m_dragging); + // only for sure + if (m_dragging) m_dragging = false; + + return false; + } + if (mouse_event.LeftDown()) { + Selection &selection = m_parent.get_selection(); + if (!selection.is_empty() && m_hover_id != -1) { + selection.start_dragging(); + + start_dragging(); + + // Let the plater know that the dragging started + m_parent.post_event( + SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); + m_parent.set_as_dirty(); + return true; + } + } else if (m_dragging) { + if (mouse_event.Dragging()) { + m_parent.set_mouse_as_dragging(); + + Point mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + UpdateData data{m_parent.mouse_ray(mouse_coord), mouse_coord}; + + on_dragging(data); + + wxGetApp().obj_manipul()->set_dirty(); + m_parent.set_as_dirty(); + return true; + } else if (mouse_event.LeftUp()) { + stop_dragging(); + + m_parent.get_gizmos_manager().update_data(); + wxGetApp().obj_manipul()->set_dirty(); + + // Let the plater know that the dragging finished, so a delayed + // refresh of the scene with the background processing data should + // be performed. + m_parent.post_event( + SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); + // updates camera target constraints + m_parent.refresh_camera_scene_box(); + return true; + } else if (mouse_event.Leaving()) { + m_dragging = false; + } + } + return false; +} + std::string GLGizmoBase::format(float value, unsigned int decimals) const { return Slic3r::string_printf("%.*f", decimals, value); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 074baa54e8..637b09f48f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -156,8 +156,6 @@ public: bool is_dragging() const { return m_dragging; } - void update(const UpdateData& data); - // returns True when Gizmo changed its state bool update_items_state(); @@ -186,9 +184,12 @@ protected: virtual CommonGizmosDataID on_get_requirements() const { return CommonGizmosDataID(0); } virtual void on_enable_grabber(unsigned int id) {} virtual void on_disable_grabber(unsigned int id) {} + + // called inside use_grabbers virtual void on_start_dragging() {} virtual void on_stop_dragging() {} - virtual void on_update(const UpdateData& data) {} + virtual void on_dragging(const UpdateData& data) {} + virtual void on_render() = 0; virtual void on_render_for_picking() = 0; virtual void on_render_input_window(float x, float y, float bottom_limit) {} @@ -204,6 +205,13 @@ protected: // Mark gizmo as dirty to Re-Render when idle() void set_dirty(); + + /// + /// + /// + /// + /// + bool use_grabbers(const wxMouseEvent &mouse_event); private: // Flag for dirty visible state of Gizmo // When True then need new rendering diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index d2c32d488a..1944878a33 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -38,6 +38,11 @@ std::string GLGizmoCut::get_tooltip() const return (m_hover_id == 0 || m_grabbers[0].dragging) ? "Z: " + format(cut_z, 2) : ""; } +bool GLGizmoCut::on_mouse(const wxMouseEvent &mouse_event) +{ + return use_grabbers(mouse_event); +} + bool GLGizmoCut::on_init() { m_grabbers.emplace_back(); @@ -76,10 +81,10 @@ void GLGizmoCut::on_start_dragging() m_drag_center.z() = m_cut_z; } -void GLGizmoCut::on_update(const UpdateData& data) +void GLGizmoCut::on_dragging(const UpdateData &data) { - if (m_hover_id != -1) - set_cut_z(m_start_z + calc_projection(data.mouse_ray)); + assert(m_hover_id != -1); + set_cut_z(m_start_z + calc_projection(data.mouse_ray)); } void GLGizmoCut::on_render() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 4007f89d47..74025c5c69 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -45,6 +45,13 @@ public: std::string get_tooltip() const override; + /// + /// Drag of plane + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + protected: virtual bool on_init() override; virtual void on_load(cereal::BinaryInputArchive& ar) override { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); } @@ -53,7 +60,7 @@ protected: virtual void on_set_state() override; virtual bool on_is_activable() const override; virtual void on_start_dragging() override; - virtual void on_update(const UpdateData& data) override; + virtual void on_dragging(const UpdateData& data) override; virtual void on_render() override; virtual void on_render_for_picking() override; virtual void on_render_input_window(float x, float y, float bottom_limit) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 9034d78d87..40a47580b7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -16,9 +16,32 @@ namespace GUI { GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) - , m_normal(Vec3d::Zero()) - , m_starting_center(Vec3d::Zero()) +{} + +bool GLGizmoFlatten::on_mouse(const wxMouseEvent &mouse_event) { + if (mouse_event.Moving()) { + // only for sure + m_mouse_left_down = false; + + if (m_hover_id != -1) m_parent.set_as_dirty(); + return false; + } + if (mouse_event.LeftDown() && m_hover_id != -1) { + Selection &selection = m_parent.get_selection(); + if (selection.is_single_full_instance()) { + // Rotate the object so the normal points downward: + selection.flattening_rotate(m_planes[m_hover_id].normal); + m_parent.do_rotate(L("Gizmo-Place on Face")); + } + m_mouse_left_down = true; + return true; + } else if (m_mouse_left_down && mouse_event.LeftUp()) { + // responsible for mouse left up + m_mouse_left_down = false; + return true; + } + return false; } bool GLGizmoFlatten::on_init() @@ -48,15 +71,6 @@ bool GLGizmoFlatten::on_is_activable() const return m_parent.get_selection().is_single_full_instance(); } -void GLGizmoFlatten::on_start_dragging() -{ - if (m_hover_id != -1) { - assert(m_planes_valid); - m_normal = m_planes[m_hover_id].normal; - m_starting_center = m_parent.get_selection().get_bounding_box().center(); - } -} - void GLGizmoFlatten::on_render() { const Selection& selection = m_parent.get_selection(); @@ -115,7 +129,6 @@ void GLGizmoFlatten::on_render_for_picking() void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { - m_starting_center = Vec3d::Zero(); if (model_object != m_old_model_object) { m_planes.clear(); m_planes_valid = false; @@ -364,13 +377,5 @@ bool GLGizmoFlatten::is_plane_update_necessary() const return false; } -Vec3d GLGizmoFlatten::get_flattening_normal() const -{ - Vec3d out = m_normal; - m_normal = Vec3d::Zero(); - m_starting_center = Vec3d::Zero(); - return out; -} - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index ab3c2c7bab..2ddcbfda2c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -18,7 +18,6 @@ class GLGizmoFlatten : public GLGizmoBase // This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself. private: - mutable Vec3d m_normal; struct PlaneData { std::vector vertices; // should be in fact local in update_planes() @@ -34,8 +33,8 @@ private: Vec3d m_first_instance_mirror; std::vector m_planes; + bool m_mouse_left_down = false; bool m_planes_valid = false; - mutable Vec3d m_starting_center; const ModelObject* m_old_model_object = nullptr; std::vector instances_matrices; @@ -46,17 +45,22 @@ public: GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); void set_flattening_data(const ModelObject* model_object); - Vec3d get_flattening_normal() const; + + /// + /// Apply rotation on select plane + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; protected: - virtual bool on_init() override; - virtual std::string on_get_name() const override; - virtual bool on_is_activable() const override; - virtual void on_start_dragging() override; - virtual void on_render() override; - virtual void on_render_for_picking() override; - virtual void on_set_state() override; - virtual CommonGizmosDataID on_get_requirements() const override; + bool on_init() override; + std::string on_get_name() const override; + bool on_is_activable() const override; + void on_render() override; + void on_render_for_picking() override; + void on_set_state() override; + CommonGizmosDataID on_get_requirements() const override; }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 614e838114..e8fe2adbfe 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -412,19 +412,33 @@ void GLGizmoHollow::delete_selected_points() select_point(NoPoints); } -void GLGizmoHollow::on_update(const UpdateData& data) +bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event) { - sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; + if (mouse_event.Moving()) return false; + if (use_grabbers(mouse_event)) return true; - if (m_hover_id != -1) { - std::pair pos_and_normal; - if (! unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) - return; - drain_holes[m_hover_id].pos = pos_and_normal.first; - drain_holes[m_hover_id].normal = -pos_and_normal.second; + // wxCoord == int --> wx/types.h + Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + Vec2d mouse_pos = mouse_coord.cast(); + + Selection & selection = m_parent.get_selection(); + static bool pending_right_up = false; + + if (mouse_event.RightDown() && selection.get_object_idx() != -1 && + gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) { + // we need to set the following right up as processed to avoid showing + // the context menu if the user release the mouse over the object + pending_right_up = true; + // event was taken care of by the SlaSupports gizmo + return true; + } + if (pending_right_up && mouse_event.RightUp()) { + pending_right_up = false; + return true; } -} + return false; +} void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) { @@ -822,6 +836,17 @@ void GLGizmoHollow::on_stop_dragging() } +void GLGizmoHollow::on_dragging(const UpdateData &data) +{ + assert(m_hover_id != -1); + std::pair pos_and_normal; + if (!unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) + return; + sla::DrainHoles &drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; + drain_holes[m_hover_id].pos = pos_and_normal.first; + drain_holes[m_hover_id].normal = -pos_and_normal.second; +} + void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 2cf08de2a0..947bbddf13 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -35,10 +35,16 @@ public: bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); } - + + /// + /// Postpone to Grabber for move + /// Detect move of object by dragging + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; private: bool on_init() override; - void on_update(const UpdateData& data) override; void on_render() override; void on_render_for_picking() override; @@ -93,6 +99,7 @@ protected: void on_set_hover_id() override; void on_start_dragging() override; void on_stop_dragging() override; + void on_dragging(const UpdateData &data) override; void on_render_input_window(float x, float y, float bottom_limit) override; virtual CommonGizmosDataID on_get_requirements() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index e73a85647e..725eed3dcd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -39,6 +39,10 @@ std::string GLGizmoMove3D::get_tooltip() const return ""; } +bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) { + return use_grabbers(mouse_event); +} + bool GLGizmoMove3D::on_init() { for (int i = 0; i < 3; ++i) { @@ -62,22 +66,23 @@ bool GLGizmoMove3D::on_is_activable() const void GLGizmoMove3D::on_start_dragging() { - if (m_hover_id != -1) { - m_displacement = Vec3d::Zero(); - const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); - m_starting_drag_position = m_grabbers[m_hover_id].center; - m_starting_box_center = box.center(); - m_starting_box_bottom_center = box.center(); - m_starting_box_bottom_center(2) = box.min(2); - } + assert(m_hover_id != -1); + + m_displacement = Vec3d::Zero(); + const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); + m_starting_drag_position = m_grabbers[m_hover_id].center; + m_starting_box_center = box.center(); + m_starting_box_bottom_center = box.center(); + m_starting_box_bottom_center(2) = box.min(2); } void GLGizmoMove3D::on_stop_dragging() { + m_parent.do_move(L("Gizmo-Move")); m_displacement = Vec3d::Zero(); } -void GLGizmoMove3D::on_update(const UpdateData& data) +void GLGizmoMove3D::on_dragging(const UpdateData& data) { if (m_hover_id == 0) m_displacement.x() = calc_projection(data); @@ -85,6 +90,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data) m_displacement.y() = calc_projection(data); else if (m_hover_id == 2) m_displacement.z() = calc_projection(data); + + Selection &selection = m_parent.get_selection(); + selection.translate(m_displacement); } void GLGizmoMove3D::on_render() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index baa2df7391..eb84e3596b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -28,19 +28,24 @@ public: double get_snap_step(double step) const { return m_snap_step; } void set_snap_step(double step) { m_snap_step = step; } - const Vec3d& get_displacement() const { return m_displacement; } - std::string get_tooltip() const override; + /// + /// Postpone to Grabber for move + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + protected: - virtual bool on_init() override; - virtual std::string on_get_name() const override; - virtual bool on_is_activable() const override; - virtual void on_start_dragging() override; - virtual void on_stop_dragging() override; - virtual void on_update(const UpdateData& data) override; - virtual void on_render() override; - virtual void on_render_for_picking() override; + bool on_init() override; + std::string on_get_name() const override; + bool on_is_activable() const override; + void on_start_dragging() override; + void on_stop_dragging() override; + void on_dragging(const UpdateData& data) override; + void on_render() override; + void on_render_for_picking() override; private: double calc_projection(const UpdateData& data) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index e164caee6d..d483c4ac0e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -570,7 +570,108 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous return false; } +bool GLGizmoPainterBase::on_mouse(const wxMouseEvent &mouse_event) +{ + // TODO: distribute implementation into gizmos itself + GLGizmosManager & mng = m_parent.get_gizmos_manager(); + GLGizmosManager::EType current_type = mng.get_current_type(); + + // wxCoord == int --> wx/types.h + Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + Vec2d mouse_pos = mouse_coord.cast(); + + if (mouse_event.Moving()) { + if (current_type == GLGizmosManager::MmuSegmentation || + current_type == GLGizmosManager::FdmSupports) + gizmo_event(SLAGizmoEventType::Moving, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), + false); + } + + // when control is down we allow scene pan and rotation even when clicking + // over some object + bool control_down = mouse_event.CmdDown(); + bool grabber_contains_mouse = (get_hover_id() != -1); + + const Selection &selection = m_parent.get_selection(); + int selected_object_idx = selection.get_object_idx(); + if (mouse_event.LeftDown() && (!control_down || grabber_contains_mouse)) { + if ((current_type == GLGizmosManager::SlaSupports || + current_type == GLGizmosManager::Hollow || + current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation) && + gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), false)) + // the gizmo got the event and took some action, there is no need + // to do anything more + return true; + } else if (mouse_event.RightDown() && !control_down && selected_object_idx != -1 && + (current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation) && + gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) { + // event was taken care of by the FdmSupports / Seam / MMUPainting gizmo + return true; + } else if (mouse_event.Dragging() && + m_parent.get_move_volume_id() != -1 && + (current_type == GLGizmosManager::SlaSupports || + current_type == GLGizmosManager::Hollow || + current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation)) + // don't allow dragging objects with the Sla gizmo on + return true; + else if (mouse_event.Dragging() && !control_down && + (current_type == GLGizmosManager::SlaSupports || + current_type == GLGizmosManager::Hollow || + current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation) && + gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), false)) { + // the gizmo got the event and took some action, no need to do + // anything more here + m_parent.set_as_dirty(); + return true; + } else if (mouse_event.Dragging() && control_down && + (mouse_event.LeftIsDown() || mouse_event.RightIsDown())) { + // CTRL has been pressed while already dragging -> stop current action + if (mouse_event.LeftIsDown()) + gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), true); + else if (mouse_event.RightIsDown()) + gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), true); + + } else if (mouse_event.LeftUp() && + (current_type == GLGizmosManager::SlaSupports || + current_type == GLGizmosManager::Hollow || + current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation) && + !m_parent.is_mouse_dragging()) { + // in case SLA/FDM gizmo is selected, we just pass the LeftUp event + // and stop processing - neither object moving or selecting is + // suppressed in that case + gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), + control_down); + return true; + } else if (mouse_event.RightUp() && + (current_type == GLGizmosManager::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation) && + !m_parent.is_mouse_dragging()) { + gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, + mouse_event.ShiftDown(), mouse_event.AltDown(), + control_down); + + return true; + } + return false; +} void GLGizmoPainterBase::update_raycast_cache(const Vec2d& mouse_position, const Camera& camera, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 97ac8e4e98..1dd9f9d7b1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -126,6 +126,15 @@ public: virtual const float get_cursor_radius_max() const { return CursorRadiusMax; } virtual const float get_cursor_radius_step() const { return CursorRadiusStep; } + /// + /// Implement when want to process mouse events in gizmo + /// Click, Right click, move, drag, ... + /// + /// Keep information about mouse click + /// Return True when use the information and don't want to + /// propagate it otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + protected: virtual void render_triangles(const Selection& selection) const; void render_cursor() const; @@ -224,9 +233,6 @@ private: protected: void on_set_state() override; - void on_start_dragging() override {} - void on_stop_dragging() override {} - virtual void on_opening() = 0; virtual void on_shutdown() = 0; virtual PainterGizmoType get_painter_type() const = 0; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 61fe6e7095..119f766ab6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -73,6 +73,13 @@ std::string GLGizmoRotate::get_tooltip() const return (m_hover_id == 0 || m_grabbers[0].dragging) ? axis + ": " + format((float)Geometry::rad2deg(m_angle), 4) : ""; } +bool GLGizmoRotate::on_mouse(const wxMouseEvent &mouse_event) +{ + return use_grabbers(mouse_event); +} + +void GLGizmoRotate::dragging(const UpdateData &data) { on_dragging(data); } + bool GLGizmoRotate::on_init() { m_grabbers.push_back(Grabber()); @@ -90,7 +97,7 @@ void GLGizmoRotate::on_start_dragging() m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; } -void GLGizmoRotate::on_update(const UpdateData& data) +void GLGizmoRotate::on_dragging(const UpdateData &data) { Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection())); @@ -445,16 +452,25 @@ GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_fil load_rotoptimize_state(); } +bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event) { + + if (mouse_event.Dragging() && m_dragging) { + // Apply new temporary rotations + TransformationType transformation_type( + TransformationType::World_Relative_Joint); + if (mouse_event.AltDown()) transformation_type.set_independent(); + m_parent.get_selection().rotate(get_rotation(), transformation_type); + } + return use_grabbers(mouse_event); +} + bool GLGizmoRotate3D::on_init() { - for (GLGizmoRotate& g : m_gizmos) { - if (!g.init()) - return false; - } + for (GLGizmoRotate& g : m_gizmos) + if (!g.init()) return false; - for (unsigned int i = 0; i < 3; ++i) { + for (unsigned int i = 0; i < 3; ++i) m_gizmos[i].set_highlight_color(AXES_COLOR[i]); - } m_shortcut_key = WXK_CONTROL_R; @@ -473,14 +489,21 @@ bool GLGizmoRotate3D::on_is_activable() const void GLGizmoRotate3D::on_start_dragging() { - if ((0 <= m_hover_id) && (m_hover_id < 3)) - m_gizmos[m_hover_id].start_dragging(); + assert(0 <= m_hover_id && m_hover_id < 3); + m_gizmos[m_hover_id].start_dragging(); } void GLGizmoRotate3D::on_stop_dragging() { - if ((0 <= m_hover_id) && (m_hover_id < 3)) - m_gizmos[m_hover_id].stop_dragging(); + assert(0 <= m_hover_id && m_hover_id < 3); + m_parent.do_rotate(L("Gizmo-Rotate")); + m_gizmos[m_hover_id].stop_dragging(); +} + +void GLGizmoRotate3D::on_dragging(const UpdateData &data) +{ + assert(0 <= m_hover_id && m_hover_id < 3); + m_gizmos[m_hover_id].dragging(data); } void GLGizmoRotate3D::on_render() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 3245c4dbe8..899b26f46a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -50,11 +50,19 @@ public: std::string get_tooltip() const override; + /// + /// Postpone to Grabber for move + /// Detect move of object by dragging + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + void dragging(const UpdateData &data); protected: bool on_init() override; std::string on_get_name() const override { return ""; } void on_start_dragging() override; - void on_update(const UpdateData& data) override; + void on_dragging(const UpdateData &data) override; void on_render() override; void on_render_for_picking() override; @@ -92,6 +100,13 @@ public: return tooltip; } + /// + /// Postpone to Rotation + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + protected: bool on_init() override; std::string on_get_name() const override; @@ -118,12 +133,8 @@ protected: bool on_is_activable() const override; void on_start_dragging() override; void on_stop_dragging() override; - void on_update(const UpdateData& data) override - { - for (GLGizmoRotate& g : m_gizmos) { - g.update(data); - } - } + void on_dragging(const UpdateData &data) override; + void on_render() override; void on_render_for_picking() override { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index b97507166b..f8c6dffdc2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -52,6 +52,22 @@ std::string GLGizmoScale3D::get_tooltip() const return ""; } +bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event) +{ + if (mouse_event.Dragging()) { + if (m_dragging) { + // Apply new temporary scale factors + TransformationType transformation_type(TransformationType::Local_Absolute_Joint); + if (mouse_event.AltDown()) transformation_type.set_independent(); + + Selection &selection = m_parent.get_selection(); + selection.scale(get_scale(), transformation_type); + if (mouse_event.CmdDown()) selection.translate(m_offset, true); + } + } + return use_grabbers(mouse_event); +} + bool GLGizmoScale3D::on_init() { for (int i = 0; i < 10; ++i) @@ -87,23 +103,25 @@ bool GLGizmoScale3D::on_is_activable() const void GLGizmoScale3D::on_start_dragging() { - if (m_hover_id != -1) - { - m_starting.drag_position = m_grabbers[m_hover_id].center; - m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); - m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box(); + assert(m_hover_id != -1); + m_starting.drag_position = m_grabbers[m_hover_id].center; + m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); + m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box(); - const Vec3d& center = m_starting.box.center(); - m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max(0), center(1), center(2)); - m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min(0), center(1), center(2)); - m_starting.pivots[2] = m_transform * Vec3d(center(0), m_starting.box.max(1), center(2)); - m_starting.pivots[3] = m_transform * Vec3d(center(0), m_starting.box.min(1), center(2)); - m_starting.pivots[4] = m_transform * Vec3d(center(0), center(1), m_starting.box.max(2)); - m_starting.pivots[5] = m_transform * Vec3d(center(0), center(1), m_starting.box.min(2)); - } + const Vec3d& center = m_starting.box.center(); + m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max(0), center(1), center(2)); + m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min(0), center(1), center(2)); + m_starting.pivots[2] = m_transform * Vec3d(center(0), m_starting.box.max(1), center(2)); + m_starting.pivots[3] = m_transform * Vec3d(center(0), m_starting.box.min(1), center(2)); + m_starting.pivots[4] = m_transform * Vec3d(center(0), center(1), m_starting.box.max(2)); + m_starting.pivots[5] = m_transform * Vec3d(center(0), center(1), m_starting.box.min(2)); } -void GLGizmoScale3D::on_update(const UpdateData& data) +void GLGizmoScale3D::on_stop_dragging() { + m_parent.do_scale(L("Gizmo-Scale")); +} + +void GLGizmoScale3D::on_dragging(const UpdateData& data) { if ((m_hover_id == 0) || (m_hover_id == 1)) do_scale_along_axis(X, data); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index 35615df4a7..1c25f3806a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -42,16 +42,22 @@ public: const Vec3d& get_scale() const { return m_scale; } void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; } - const Vec3d& get_offset() const { return m_offset; } - std::string get_tooltip() const override; + /// + /// Postpone to Grabber for scale + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; + protected: virtual bool on_init() override; virtual std::string on_get_name() const override; virtual bool on_is_activable() const override; virtual void on_start_dragging() override; - virtual void on_update(const UpdateData& data) override; + virtual void on_stop_dragging() override; + virtual void on_dragging(const UpdateData& data) override; virtual void on_render() override; virtual void on_render_for_picking() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 9170db6039..078a24176c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -530,22 +530,6 @@ void GLGizmoSlaSupports::delete_selected_points(bool force) select_point(NoPoints); } -void GLGizmoSlaSupports::on_update(const UpdateData& data) -{ - if (! m_editing_mode) - return; - else { - if (m_hover_id != -1 && (! m_editing_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { - std::pair pos_and_normal; - if (! unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) - return; - m_editing_cache[m_hover_id].support_point.pos = pos_and_normal.first; - m_editing_cache[m_hover_id].support_point.is_new_island = false; - m_editing_cache[m_hover_id].normal = pos_and_normal.second; - } - } -} - std::vector GLGizmoSlaSupports::get_config_options(const std::vector& keys) const { std::vector out; @@ -966,7 +950,21 @@ void GLGizmoSlaSupports::on_stop_dragging() m_point_before_drag = CacheEntry(); } +void GLGizmoSlaSupports::on_dragging(const UpdateData &data) +{ + assert(m_hover_id != -1); + if (!m_editing_mode) return; + if (m_editing_cache[m_hover_id].support_point.is_new_island && m_lock_unique_islands) + return; + + std::pair pos_and_normal; + if (!unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) + return; + m_editing_cache[m_hover_id].support_point.pos = pos_and_normal.first; + m_editing_cache[m_hover_id].support_point.is_new_island = false; + m_editing_cache[m_hover_id].normal = pos_and_normal.second; +} void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) { @@ -1103,6 +1101,34 @@ void GLGizmoSlaSupports::reslice_SLA_supports(bool postpone_error_messages) cons }); } +bool GLGizmoSlaSupports::on_mouse(const wxMouseEvent &mouse_event){ + if (mouse_event.Moving()) return false; + if (use_grabbers(mouse_event)) return true; + + // wxCoord == int --> wx/types.h + Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + Vec2d mouse_pos = mouse_coord.cast(); + + Selection &selection = m_parent.get_selection(); + static bool pending_right_up = false; + + if (mouse_event.RightDown() && + selection.get_object_idx() != -1 && + gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) { + // we need to set the following right up as processed to avoid showing + // the context menu if the user release the mouse over the object + pending_right_up = true; + // event was taken care of by the SlaSupports gizmo + return true; + } + if (pending_right_up && mouse_event.RightUp()) { + pending_right_up = false; + return true; + } + + return false; +} + void GLGizmoSlaSupports::get_data_from_backend() { if (! has_backend_supports()) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 35e6a73089..c19b29e0bf 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -70,10 +70,16 @@ public: bool wants_enter_leave_snapshots() const override { return true; } std::string get_gizmo_entering_text() const override { return _u8L("Entering SLA support points"); } std::string get_gizmo_leaving_text() const override { return _u8L("Leaving SLA support points"); } + + /// + /// Process mouse event + /// + /// Keep information about mouse click + /// Return True when use the information otherwise False. + bool on_mouse(const wxMouseEvent &mouse_event) override; private: bool on_init() override; - void on_update(const UpdateData& data) override; void on_render() override; void on_render_for_picking() override; @@ -103,7 +109,6 @@ private: std::vector get_config_options(const std::vector& keys) const; bool is_mesh_point_clipped(const Vec3d& point) const; - bool is_point_in_hole(const Vec3f& pt) const; //void find_intersecting_facets(const igl::AABB* aabb, const Vec3f& normal, double offset, std::vector& out) const; // Methods that do the model_object and editing cache synchronization, @@ -126,13 +131,13 @@ private: protected: void on_set_state() override; void on_set_hover_id() override - { if (! m_editing_mode || (int)m_editing_cache.size() <= m_hover_id) m_hover_id = -1; } void on_start_dragging() override; void on_stop_dragging() override; + void on_dragging(const UpdateData &data) override; void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 1b81dc10a3..1a5e453ce8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -38,6 +38,7 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) , m_enabled(false) , m_icons_texture_dirty(true) , m_current(Undefined) + , m_hover(Undefined) , m_tooltip("") , m_serializing(false) { @@ -46,33 +47,34 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) std::vector GLGizmosManager::get_selectable_idxs() const { std::vector out; + out.reserve(m_gizmos.size()); for (size_t i=0; iis_selectable()) out.push_back(i); return out; } -size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const +GLGizmosManager::EType GLGizmosManager::get_gizmo_from_mouse(const Vec2d &mouse_pos) const { - if (! m_enabled) - return Undefined; + if (!m_enabled) return Undefined; - float cnv_h = (float)m_parent.get_canvas_size().get_height(); - float height = get_scaled_total_height(); + float cnv_h = (float) m_parent.get_canvas_size().get_height(); + float height = get_scaled_total_height(); float icons_size = m_layout.scaled_icons_size(); - float border = m_layout.scaled_border(); - float stride_y = m_layout.scaled_stride_y(); - float top_y = 0.5f * (cnv_h - height) + border; + float border = m_layout.scaled_border(); + float stride_y = m_layout.scaled_stride_y(); + float top_y = 0.5f * (cnv_h - height) + border; // is mouse horizontally in the area? - if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) { + if ((border <= (float) mouse_pos(0) && + ((float) mouse_pos(0) <= border + icons_size))) { // which icon is it on? - size_t from_top = (size_t)((float)mouse_pos(1) - top_y) / stride_y; + size_t from_top = (size_t) ((float) mouse_pos(1) - top_y) / stride_y; // is it really on the icon or already past the border? - if ((float)mouse_pos(1) <= top_y + from_top * stride_y + icons_size) { + if ((float) mouse_pos(1) <= top_y + from_top * stride_y + icons_size) { std::vector selectable = get_selectable_idxs(); - if (from_top < selectable.size()) - return selectable[from_top]; + if (from_top < selectable.size()) + return static_cast(selectable[from_top]); } } return Undefined; @@ -177,9 +179,13 @@ void GLGizmosManager::reset_all_states() bool GLGizmosManager::open_gizmo(EType type) { - int idx = int(type); - if (m_gizmos[idx]->is_activable() - && activate_gizmo(m_current == idx ? Undefined : (EType)idx)) { + int idx = static_cast(type); + + // re-open same type cause closing + if (m_current == type) type = Undefined; + + if (m_gizmos[idx]->is_activable() && activate_gizmo(type)) { + // remove update data into gizmo itself update_data(); return true; } @@ -219,16 +225,7 @@ void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable) m_gizmos[type]->disable_grabber(id); } -void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos) -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos)); -} - +// TODO: divide into gizmo: on init + on selection change void GLGizmosManager::update_data() { if (!m_enabled) @@ -343,14 +340,6 @@ void GLGizmosManager::stop_dragging() m_gizmos[m_current]->stop_dragging(); } -Vec3d GLGizmosManager::get_displacement() const -{ - if (!m_enabled) - return Vec3d::Zero(); - - return dynamic_cast(m_gizmos[Move].get())->get_displacement(); -} - Vec3d GLGizmosManager::get_scale() const { if (!m_enabled) @@ -367,14 +356,6 @@ void GLGizmosManager::set_scale(const Vec3d& scale) dynamic_cast(m_gizmos[Scale].get())->set_scale(scale); } -Vec3d GLGizmosManager::get_scale_offset() const -{ - if (!m_enabled || m_gizmos.empty()) - return Vec3d::Zero(); - - return dynamic_cast(m_gizmos[Scale].get())->get_offset(); -} - Vec3d GLGizmosManager::get_rotation() const { if (!m_enabled || m_gizmos.empty()) @@ -390,14 +371,6 @@ void GLGizmosManager::set_rotation(const Vec3d& rotation) dynamic_cast(m_gizmos[Rotate].get())->set_rotation(rotation); } -Vec3d GLGizmosManager::get_flattening_normal() const -{ - if (!m_enabled || m_gizmos.empty()) - return Vec3d::Zero(); - - return dynamic_cast(m_gizmos[Flatten].get())->get_flattening_normal(); -} - void GLGizmosManager::set_flattening_data(const ModelObject* model_object) { if (!m_enabled || m_gizmos.empty()) @@ -517,7 +490,7 @@ std::string GLGizmosManager::get_tooltip() const return (curr != nullptr) ? curr->get_tooltip() : ""; } -bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt) +bool GLGizmosManager::on_mouse_wheel(const wxMouseEvent &evt) { bool processed = false; @@ -530,227 +503,108 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt) return processed; } -bool GLGizmosManager::on_mouse(wxMouseEvent& evt) -{ - // used to set a right up event as processed when needed - static bool pending_right_up = false; - - Point pos(evt.GetX(), evt.GetY()); - Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY()); - - Selection& selection = m_parent.get_selection(); - int selected_object_idx = selection.get_object_idx(); - bool processed = false; - - // when control is down we allow scene pan and rotation even when clicking over some object - bool control_down = evt.CmdDown(); - - // mouse anywhere - if (evt.Moving()) { - m_tooltip = update_hover_state(mouse_pos); - if (m_current == MmuSegmentation || m_current == FdmSupports) - gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown()); - } else if (evt.LeftUp()) { - if (m_mouse_capture.left) { - processed = true; - m_mouse_capture.left = false; +bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) { + assert(m_enabled); + // keep information about events to process + struct MouseCapture + { + bool left = false; + bool middle = false; + bool right = false; + bool exist_tooltip = false; + MouseCapture() = default; + bool any() const { return left || middle || right; } + void reset() { + left = false; + middle = false; + right = false; } - else if (is_dragging()) { - switch (m_current) { - case Move: { m_parent.do_move(L("Gizmo-Move")); break; } - case Scale: { m_parent.do_scale(L("Gizmo-Scale")); break; } - case Rotate: { m_parent.do_rotate(L("Gizmo-Rotate")); break; } - default: break; - } + }; + static MouseCapture mc; - stop_dragging(); - update_data(); + // wxCoord == int --> wx/types.h + Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + Vec2d mouse_pos = mouse_coord.cast(); - wxGetApp().obj_manipul()->set_dirty(); - // Let the plater know that the dragging finished, so a delayed refresh - // of the scene with the background processing data should be performed. - m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); - // updates camera target constraints - m_parent.refresh_camera_scene_box(); + EType gizmo = get_gizmo_from_mouse(mouse_pos); + bool selected_gizmo = gizmo != Undefined; - processed = true; - } -// else -// return false; - } - else if (evt.MiddleUp()) { - if (m_mouse_capture.middle) { - processed = true; - m_mouse_capture.middle = false; - } - else + // fast reaction on move mouse + if (mouse_event.Moving()) { + assert(!mc.any()); + if (selected_gizmo) { + mc.exist_tooltip = true; + update_hover_state(gizmo); + // at this moment is enebled to process mouse move under gizmo + // tools bar e.g. Do not interupt dragging. return false; + } else if (mc.exist_tooltip) { + // first move out of gizmo tool bar - unselect tooltip + mc.exist_tooltip = false; + update_hover_state(Undefined); + return false; + } + return false; } - else if (evt.RightUp()) { - if (pending_right_up) { - pending_right_up = false; + + if (selected_gizmo) { + // mouse is above toolbar + if (mouse_event.LeftDown() || mouse_event.LeftDClick()) { + mc.left = true; + open_gizmo(gizmo); + return true; + } else if (mouse_event.RightDown()) { + mc.right = true; + return true; + } else if (mouse_event.MiddleDown()) { + mc.middle = true; return true; } - if (m_mouse_capture.right) { - processed = true; - m_mouse_capture.right = false; - } -// else -// return false; - } - else if (evt.Dragging() && !is_dragging()) { - if (m_mouse_capture.any()) - // if the button down was done on this toolbar, prevent from dragging into the scene - processed = true; -// else -// return false; - } - else if (evt.Dragging() && is_dragging()) { - if (!m_parent.get_wxglcanvas()->HasCapture()) - m_parent.get_wxglcanvas()->CaptureMouse(); - - m_parent.set_mouse_as_dragging(); - update(m_parent.mouse_ray(pos), pos); - - switch (m_current) - { - case Move: - { - // Apply new temporary offset - selection.translate(get_displacement()); - wxGetApp().obj_manipul()->set_dirty(); - break; - } - case Scale: - { - // Apply new temporary scale factors - TransformationType transformation_type(TransformationType::Local_Absolute_Joint); - if (evt.AltDown()) - transformation_type.set_independent(); - selection.scale(get_scale(), transformation_type); - if (control_down) - selection.translate(get_scale_offset(), true); - wxGetApp().obj_manipul()->set_dirty(); - break; - } - case Rotate: - { - // Apply new temporary rotations - TransformationType transformation_type(TransformationType::World_Relative_Joint); - if (evt.AltDown()) - transformation_type.set_independent(); - selection.rotate(get_rotation(), transformation_type); - wxGetApp().obj_manipul()->set_dirty(); - break; - } - default: - break; - } - - m_parent.set_as_dirty(); - processed = true; } - if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) { - // mouse is outside the toolbar - m_tooltip.clear(); - - if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) { - if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) - && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown())) - // the gizmo got the event and took some action, there is no need to do anything more - processed = true; - else if (!selection.is_empty() && grabber_contains_mouse()) { - update_data(); - selection.start_dragging(); - start_dragging(); - - // Let the plater know that the dragging started - m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); - - if (m_current == Flatten) { - // Rotate the object so the normal points downward: - m_parent.do_flatten(get_flattening_normal(), L("Gizmo-Place on Face")); - wxGetApp().obj_manipul()->set_dirty(); - } - - m_parent.set_as_dirty(); - processed = true; + if (mc.any()) { + // Check if exist release of event started above toolbar? + if (mouse_event.Dragging()) { + if (!selected_gizmo && mc.exist_tooltip) { + // dragging out of gizmo let tooltip disapear + mc.exist_tooltip = false; + update_hover_state(Undefined); } + // draging start on toolbar so no propagation into scene + return true; + } else if (mc.left && mouse_event.LeftUp()) { + mc.left = false; + return true; + } else if (mc.right && mouse_event.RightUp()) { + mc.right = false; + return true; + } else if (mc.middle && mouse_event.MiddleUp()) { + mc.middle = false; + return true; } - else if (evt.RightDown() && selected_object_idx != -1 && (m_current == SlaSupports || m_current == Hollow) - && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { - // we need to set the following right up as processed to avoid showing the context menu if the user release the mouse over the object - pending_right_up = true; - // event was taken care of by the SlaSupports gizmo - processed = true; - } - else if (evt.RightDown() && !control_down && selected_object_idx != -1 && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) - && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { - // event was taken care of by the FdmSupports / Seam / MMUPainting gizmo - processed = true; - } - else if (evt.Dragging() && m_parent.get_move_volume_id() != -1 - && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)) - // don't allow dragging objects with the Sla gizmo on - processed = true; - else if (evt.Dragging() && !control_down && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) - && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown())) { - // the gizmo got the event and took some action, no need to do anything more here - m_parent.set_as_dirty(); - processed = true; - } - else if (evt.Dragging() && control_down && (evt.LeftIsDown() || evt.RightIsDown())) { - // CTRL has been pressed while already dragging -> stop current action - if (evt.LeftIsDown()) - gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); - else if (evt.RightIsDown()) - gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); - } - else if (evt.LeftUp() && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) { - // in case SLA/FDM gizmo is selected, we just pass the LeftUp event and stop processing - neither - // object moving or selecting is suppressed in that case - gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down); - processed = true; - } - else if (evt.LeftUp() && m_current == Flatten && m_gizmos[m_current]->get_hover_id() != -1) { - // to avoid to loose the selection when user clicks an the white faces of a different object while the Flatten gizmo is active - selection.stop_dragging(); - wxGetApp().obj_manipul()->set_dirty(); - processed = true; - } - else if (evt.RightUp() && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) { - gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down); - processed = true; - } - else if (evt.LeftUp()) { - selection.stop_dragging(); - wxGetApp().obj_manipul()->set_dirty(); - } - } - else { - // mouse inside toolbar - if (evt.LeftDown() || evt.LeftDClick()) { - m_mouse_capture.left = true; - m_mouse_capture.parent = &m_parent; - processed = true; - if (!selection.is_empty()) { - update_on_off_state(mouse_pos); - update_data(); - m_parent.set_as_dirty(); - } - } - else if (evt.MiddleDown()) { - m_mouse_capture.middle = true; - m_mouse_capture.parent = &m_parent; - } - else if (evt.RightDown()) { - m_mouse_capture.right = true; - m_mouse_capture.parent = &m_parent; - } + + // event out of window is not porocessed + // left down on gizmo -> keep down -> move out of window -> release left + if (mouse_event.Leaving()) mc.reset(); } + return false; +} - return processed; +bool GLGizmosManager::on_mouse(const wxMouseEvent &mouse_event) +{ + if (!m_enabled) return false; + + // tool bar wants to use event? + if (gizmos_toolbar_on_mouse(mouse_event)) return true; + + // current gizmo wants to use event? + if (m_current != Undefined && + // check if gizmo override method could be slower than simple call virtual function + // &m_gizmos[m_current]->on_mouse != &GLGizmoBase::on_mouse && + m_gizmos[m_current]->on_mouse(mouse_event)) + return true; + + return false; } bool GLGizmosManager::on_char(wxKeyEvent& evt) @@ -1182,42 +1036,26 @@ bool GLGizmosManager::generate_icons_texture() const return res; } -void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos) +void GLGizmosManager::update_hover_state(const EType &type) { - if (!m_enabled) + assert(m_enabled); + if (type == Undefined) { + m_hover = Undefined; + m_tooltip.clear(); return; - - size_t idx = get_gizmo_idx_from_mouse(mouse_pos); - if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx) { - activate_gizmo(m_current == idx ? Undefined : (EType)idx); - wxGetApp().obj_list()->select_object_item((EType)idx <= Rotate); - } -} - -std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos) -{ - std::string name = ""; - - if (!m_enabled) - return name; - - m_hover = Undefined; - - size_t idx = get_gizmo_idx_from_mouse(mouse_pos); - if (idx != Undefined) { - name = m_gizmos[idx]->get_name(); - - if (m_gizmos[idx]->is_activable()) - m_hover = (EType)idx; } - return name; + const GLGizmoBase &hovered_gizmo = *m_gizmos[type]; + m_hover = hovered_gizmo.is_activable() ? type : Undefined; + m_tooltip = hovered_gizmo.get_name(); } bool GLGizmosManager::activate_gizmo(EType type) { - if (m_gizmos.empty() || m_current == type) - return true; + assert(!m_gizmos.empty()); + + // already activated + if (m_current == type) return true; if (m_current != Undefined) { // clean up previous gizmo @@ -1226,31 +1064,36 @@ bool GLGizmosManager::activate_gizmo(EType type) if (old_gizmo.get_state() != GLGizmoBase::Off) return false; // gizmo refused to be turned off, do nothing. - if (!m_serializing - && old_gizmo.wants_enter_leave_snapshots()) - Plater::TakeSnapshot snapshot(wxGetApp().plater(), - old_gizmo.get_gizmo_leaving_text(), - UndoRedo::SnapshotType::LeavingGizmoWithAction); + if (!m_serializing && old_gizmo.wants_enter_leave_snapshots()) + Plater::TakeSnapshot + snapshot(wxGetApp().plater(), + old_gizmo.get_gizmo_leaving_text(), + UndoRedo::SnapshotType::LeavingGizmoWithAction); } - // check deactivation of gizmo if (type == Undefined) { - m_current = type; + // it is deactivation of gizmo + m_current = Undefined; return true; } // set up new gizmo GLGizmoBase& new_gizmo = *m_gizmos[type]; + if (!new_gizmo.is_activable()) return false; + if (!m_serializing && new_gizmo.wants_enter_leave_snapshots()) Plater::TakeSnapshot snapshot(wxGetApp().plater(), - new_gizmo.get_gizmo_entering_text(), - UndoRedo::SnapshotType::EnteringGizmo); + new_gizmo.get_gizmo_entering_text(), + UndoRedo::SnapshotType::EnteringGizmo); m_current = type; new_gizmo.set_state(GLGizmoBase::On); - if (new_gizmo.get_state() != GLGizmoBase::On) + if (new_gizmo.get_state() != GLGizmoBase::On) { + m_current = Undefined; return false; // gizmo refused to be turned on. + } + // sucessful activation of gizmo return true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index f0ad185b5e..9333c08949 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -102,28 +102,22 @@ private: std::pair m_highlight; // bool true = higlightedShown, false = highlightedHidden std::vector get_selectable_idxs() const; - size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const; + EType get_gizmo_from_mouse(const Vec2d &mouse_pos) const; bool activate_gizmo(EType type); - struct MouseCapture - { - bool left; - bool middle; - bool right; - GLCanvas3D* parent; - - MouseCapture() { reset(); } - - bool any() const { return left || middle || right; } - void reset() { left = middle = right = false; parent = nullptr; } - }; - - MouseCapture m_mouse_capture; std::string m_tooltip; bool m_serializing; std::unique_ptr m_common_gizmos_data; + /// + /// Process mouse event on gizmo toolbar + /// + /// Event descriptor + /// TRUE when take responsibility for event otherwise FALSE. + /// On true, event should not be process by others. + /// On false, event should be process by others. + bool gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event); public: explicit GLGizmosManager(GLCanvas3D& parent); @@ -180,7 +174,6 @@ public: void set_hover_id(int id); void enable_grabber(EType type, unsigned int id, bool enable); - void update(const Linef3& mouse_ray, const Point& mouse_pos); void update_data(); EType get_current_type() const { return m_current; } @@ -194,18 +187,12 @@ public: void start_dragging(); void stop_dragging(); - Vec3d get_displacement() const; - Vec3d get_scale() const; void set_scale(const Vec3d& scale); - Vec3d get_scale_offset() const; - Vec3d get_rotation() const; void set_rotation(const Vec3d& rotation); - Vec3d get_flattening_normal() const; - void set_flattening_data(const ModelObject* model_object); void set_sla_support_data(ModelObject* model_object); @@ -229,8 +216,8 @@ public: std::string get_tooltip() const; - bool on_mouse(wxMouseEvent& evt); - bool on_mouse_wheel(wxMouseEvent& evt); + bool on_mouse(const wxMouseEvent &mouse_event); + bool on_mouse_wheel(const wxMouseEvent &evt); bool on_char(wxKeyEvent& evt); bool on_key(wxKeyEvent& evt); @@ -253,8 +240,7 @@ private: bool generate_icons_texture() const; - void update_on_off_state(const Vec2d& mouse_pos); - std::string update_hover_state(const Vec2d& mouse_pos); + void update_hover_state(const EType &type); bool grabber_contains_mouse() const; };