diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6fae6c4976..b492d23543 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4667,15 +4667,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_center() { if (m_model == nullptr) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 54c033ebef..b1f73fefab 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -957,7 +957,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_center(); void do_mirror(const std::string& snapshot_type); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 3e6b699878..a6847b00fd 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -5858,6 +5858,12 @@ Sidebar& GUI_App::sidebar() return plater_->sidebar(); } +GizmoObjectManipulation *GUI_App::obj_manipul() +{ + // If this method is called before plater_ has been initialized, return nullptr (to avoid a crash) + return (plater_ != nullptr) ? &plater_->get_view3D_canvas3D()->get_gizmos_manager().get_object_manipulation() : nullptr; +} + ObjectSettings* GUI_App::obj_settings() { return sidebar().obj_settings(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 44411b361c..d72a217b93 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -129,6 +129,7 @@ enum CameraMenuIDs { class Tab; class ConfigWizard; +class GizmoObjectManipulation; static wxString dots("...", wxConvUTF8); @@ -529,6 +530,7 @@ private: #endif /* __APPLE */ Sidebar& sidebar(); + GizmoObjectManipulation* obj_manipul(); ObjectSettings* obj_settings(); ObjectList* obj_list(); ObjectLayers* obj_layers(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index a7851318a6..b3aa8ef870 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -434,9 +434,9 @@ void GLGizmoAdvancedCut::on_stop_dragging() } } -void GLGizmoAdvancedCut::on_update(const UpdateData& data) +void GLGizmoAdvancedCut::on_dragging(const UpdateData &data) { - GLGizmoRotate3D::on_update(data); + GLGizmoRotate3D::on_dragging(data); Vec3d rotation; for (int i = 0; i < 3; i++) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index a61fcdc1e1..007a95e62e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -139,17 +139,17 @@ public: virtual bool apply_clipping_plane() { return m_connectors_editing; } protected: - virtual bool on_init(); - virtual void on_load(cereal::BinaryInputArchive &ar) override; - virtual void on_save(cereal::BinaryOutputArchive &ar) const override; - virtual std::string on_get_name() const; - virtual void on_set_state(); - virtual bool on_is_activable() const; - virtual CommonGizmosDataID on_get_requirements() const override; - virtual void on_start_dragging() override; - virtual void on_stop_dragging() override; - virtual void on_update(const UpdateData& data); - virtual void on_render(); + bool on_init() override; + void on_load(cereal::BinaryInputArchive &ar) override; + void on_save(cereal::BinaryOutputArchive &ar) const override; + std::string on_get_name() const override; + void on_set_state() override; + bool on_is_activable() const override; + CommonGizmosDataID on_get_requirements() const override; + void on_start_dragging() override; + void on_stop_dragging() override; + void on_dragging(const UpdateData& data) override; + void on_render() override; virtual void on_render_input_window(float x, float y, float bottom_limit); void show_tooltip_information(float x, float y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 6b3eede5c3..8d59ea819a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -211,10 +211,15 @@ void GLGizmoBase::set_icon_filename(const std::string &filename) { 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(); } @@ -260,18 +265,12 @@ void GLGizmoBase::stop_dragging() //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("this %1%, m_hover_id=%2%\n")%this %m_hover_id; } -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; -}; +} bool GLGizmoBase::GizmoImguiBegin(const std::string &name, int flags) { @@ -345,6 +344,62 @@ void GLGizmoBase::render_grabbers(float size) const shader->stop_using(); } +// 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 e58eaee6be..8094d36f55 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -199,8 +199,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(); @@ -237,9 +235,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_input_window(float x, float y, float bottom_limit) {} @@ -262,6 +263,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/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 6b44af03d8..2b2b73a195 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -18,9 +18,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() @@ -51,15 +74,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(); @@ -121,43 +135,8 @@ void GLGizmoFlatten::on_unregister_raycasters_for_picking() m_planes_casters.clear(); } -/* -void GLGizmoFlatten::on_render_for_picking() -{ - const Selection& selection = m_parent.get_selection(); - GLShaderProgram* shader = wxGetApp().get_shader("flat"); - if (shader == nullptr) - return; - - shader->start_using(); - - glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glDisable(GL_BLEND)); - - if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) { - const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); - const Camera& camera = wxGetApp().plater()->get_camera(); - const Transform3d view_model_matrix = camera.get_view_matrix() * - Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m; - - shader->set_uniform("view_model_matrix", view_model_matrix); - shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - if (this->is_plane_update_necessary()) - update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) { - m_planes[i].vbo.set_color(picking_color_component(i)); - m_planes[i].vbo.render(); - } - } - - glsafe(::glEnable(GL_CULL_FACE)); - shader->stop_using(); -} -*/ - void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { - m_starting_center = Vec3d::Zero(); if (model_object != m_old_model_object) { m_planes.clear(); on_unregister_raycasters_for_picking(); @@ -414,13 +393,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 73c5d32624..54d931577d 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() @@ -36,7 +35,7 @@ private: std::vector m_planes; std::vector> m_planes_casters; - mutable Vec3d m_starting_center; + bool m_mouse_left_down = false; const ModelObject* m_old_model_object = nullptr; std::vector instances_matrices; @@ -47,18 +46,23 @@ 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_register_raycasters_for_picking() override; - virtual void on_unregister_raycasters_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_register_raycasters_for_picking() override; + void on_unregister_raycasters_for_picking() override; + void on_set_state() override; + CommonGizmosDataID on_get_requirements() const override; }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp index df9def7ab4..fb19ff6459 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp @@ -84,6 +84,27 @@ bool GLGizmoMeshBoolean::gizmo_event(SLAGizmoEventType action, const Vec2d& mous return true; } +bool GLGizmoMeshBoolean::on_mouse(const wxMouseEvent &mouse_event) +{ + // wxCoord == int --> wx/types.h + Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + Vec2d mouse_pos = mouse_coord.cast(); + + // 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); + if (mouse_event.LeftDown()) { + if ((!control_down || grabber_contains_mouse) && + 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; + } + + return false; +} + bool GLGizmoMeshBoolean::on_init() { m_shortcut_key = WXK_CONTROL_B; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp index f88ac85c97..c012a68dca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp @@ -55,7 +55,16 @@ public: m_src.reset(); } - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); + + /// + /// 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 bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 1925cd7fa5..63857189cd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -43,6 +43,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) { @@ -70,22 +74,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); @@ -93,6 +98,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 c962348848..bbe88f5942 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -40,20 +40,25 @@ 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_register_raycasters_for_picking() override; - virtual void on_unregister_raycasters_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_register_raycasters_for_picking() override; + void on_unregister_raycasters_for_picking() override; //BBS: GUI refactor: add object manipulation virtual void on_render_input_window(float x, float y, float bottom_limit); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 4afaf06b49..c9daac5797 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -900,7 +900,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 || + current_type == GLGizmosManager::Text) + 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::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation || + current_type == GLGizmosManager::Text || + current_type == GLGizmosManager::Cut || + current_type == GLGizmosManager::MeshBoolean) && + 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 || + current_type == GLGizmosManager::Cut) && + gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) { + // event was taken care of by the FdmSupports / Seam / MMUPainting / Cut gizmo + return true; + } else if (mouse_event.Dragging() && + m_parent.get_move_volume_id() != -1 && + (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::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation || + current_type == GLGizmosManager::Cut) && + 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::FdmSupports || + current_type == GLGizmosManager::Seam || + current_type == GLGizmosManager::MmuSegmentation || + current_type == GLGizmosManager::Cut) && + !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 || + current_type == GLGizmosManager::Cut) && + !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 cd397ab4e2..15f7c1868d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -206,6 +206,15 @@ public: virtual const float get_cursor_height_max() const { return CursorHeightMax; } virtual const float get_cursor_height_step() const { return CursorHeightStep; } + /// + /// 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(); @@ -349,9 +358,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 e6a2dd6973..6bc7cbaa5a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -51,6 +51,13 @@ std::string GLGizmoRotate::get_tooltip() const return (m_hover_id == 0 || m_grabbers.front().dragging) ? axis + ": " + format(float(Geometry::rad2deg(m_angle)), 2) : ""; } +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()); @@ -69,7 +76,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) { const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection())); @@ -456,16 +463,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; @@ -486,14 +502,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 cc00409c00..acd2c2876e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -66,11 +66,19 @@ public: void set_center(const Vec3d &point) { m_custom_center = point; } + /// + /// 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; private: @@ -121,6 +129,13 @@ public: m_gizmos[Z].set_center(point); } + /// + /// 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; @@ -143,11 +158,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; virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index f6bbf4c523..6215e71525 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -74,6 +74,23 @@ void GLGizmoScale3D::enable_ununiversal_scale(bool enable) m_grabbers[i].enabled = enable; } +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) { @@ -110,24 +127,27 @@ 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.plane_center = m_grabbers[4].center; - m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].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.plane_center = m_grabbers[4].center; + m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].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.x(), center.y(), center.z()); - m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min.x(), center.y(), center.z()); - m_starting.pivots[2] = m_transform * Vec3d(center.x(), m_starting.box.max.y(), center.z()); - m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z()); - m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z()); - m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z()); - } + const Vec3d& center = m_starting.box.center(); + m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max.x(), center.y(), center.z()); + m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min.x(), center.y(), center.z()); + m_starting.pivots[2] = m_transform * Vec3d(center.x(), m_starting.box.max.y(), center.z()); + m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z()); + m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z()); + m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z()); } -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 a4b5a064c1..cb504eadb8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -60,17 +60,24 @@ 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; void enable_ununiversal_scale(bool enable); + + /// + /// 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_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 941f134e78..518825ca5c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -253,7 +253,7 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit } else if (action == SLAGizmoEventType::LeftDown) { if (!selection.is_empty() && get_hover_id() != -1) { - start_dragging(); + //start_dragging(); return true; } @@ -513,7 +513,7 @@ void GLGizmoText::on_render_for_picking() } */ -void GLGizmoText::on_update(const UpdateData &data) +void GLGizmoText::on_dragging(const UpdateData &data) { Vec2d mouse_pos = Vec2d(data.mouse_pos.x(), data.mouse_pos.y()); const ModelObject *mo = m_c->selection_info()->model_object(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp index 0eaf1304ca..801eaddcd7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp @@ -91,7 +91,7 @@ protected: virtual std::string on_get_name() const override; virtual bool on_is_activable() const override; virtual void on_render() override; - virtual void on_update(const UpdateData &data) override; + virtual void on_dragging(const UpdateData &data) override; void push_combo_style(const float scale); void pop_combo_style(); void push_button_style(bool pressed); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 19a3863751..3187e42664 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -45,6 +45,7 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) , m_enabled(false) , m_icons_texture_dirty(true) , m_current(Undefined) + , m_hover(Undefined) , m_tooltip("") , m_serializing(false) //BBS: GUI refactor: add object manipulation in gizmo @@ -55,6 +56,7 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) std::vector GLGizmosManager::get_selectable_idxs() const { std::vector out; + out.reserve(m_gizmos.size()); if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { for (size_t i = 0; i < m_gizmos.size(); ++i) if (m_gizmos[i]->get_sprite_id() == (unsigned int)MmuSegmentation) @@ -69,21 +71,19 @@ std::vector GLGizmosManager::get_selectable_idxs() const } //BBS: GUI refactor: GLToolbar&&Gizmo adjust -//when judge the mouse position, {0, 0} is at the left-up corner, and no need to multiply camera_zoom -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; - 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 border = m_layout.scaled_border(); //BBS: GUI refactor: GLToolbar&&Gizmo adjust float cnv_w = (float)m_parent.get_canvas_size().get_width(); float width = get_scaled_total_width(); -#if BBS_TOOLBAR_ON_TOP //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; const float separator_width = m_parent.get_separator_toolbar_width(); float top_x = std::max(0.0f, 0.5f * (cnv_w - (width + separator_width + m_parent.get_main_toolbar_width() - m_parent.get_collapse_toolbar_width() + m_parent.get_assemble_view_toolbar_width()))); @@ -104,31 +104,9 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const if ((float)mouse_pos(0) <= top_x + from_left * stride_x + icons_size) { std::vector selectable = get_selectable_idxs(); if (from_left < selectable.size()) - return selectable[from_left]; + return static_cast(selectable[from_left]); } } -#else - //float top_y = 0.5f * (cnv_h - height) + border; - float top_x = cnv_w - width; - float top_y = 0.5f * (cnv_h - height + m_parent.get_main_toolbar_height() - m_parent.get_assemble_view_toolbar_width()) + border; - float stride_y = m_layout.scaled_stride_y(); - - // is mouse horizontally in the area? - //if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) { - if (((top_x + border) <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= (top_x + border + icons_size))) { - // which icon is it on? - size_t from_top = (size_t)((float)mouse_pos(1) - top_y) / stride_y; - if (from_top < 0) - return Undefined; - // is it really on the icon or already past the border? - 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]; - } - } -#endif - return Undefined; } @@ -346,9 +324,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(); #ifdef __WXOSX__ m_parent.post_event(SimpleEvent(wxEVT_PAINT)); @@ -390,16 +372,6 @@ 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)); -} - void GLGizmosManager::update_assemble_view_data() { if (m_assemble_view_data) { @@ -410,6 +382,7 @@ void GLGizmosManager::update_assemble_view_data() } } +// TODO: divide into gizmo: on init + on selection change void GLGizmosManager::update_data() { if (!m_enabled) @@ -534,14 +507,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) @@ -558,14 +523,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()) @@ -587,14 +544,6 @@ void GLGizmosManager::finish_cut_rotation() dynamic_cast(m_gizmos[Cut].get())->finish_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()) @@ -736,7 +685,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; @@ -756,253 +705,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 || m_current == Text) - // BBS - gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()); - } 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(("Tool-Move")); break; } - case Scale: { m_parent.do_scale(("Tool-Scale")); break; } - case Rotate: { m_parent.do_rotate(("Tool-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(); - // BBS - //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; - } - 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()); - // BBS - //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 && m_gizmos[m_current].get()->get_hover_id() < 6) - selection.translate(get_scale_offset(), true); - // BBS - //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); - // BBS - //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 || m_current == Text || m_current == Cut || m_current == MeshBoolean) - && 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("Tool-Lay on Face")); - // BBS - //wxGetApp().obj_manipul()->set_dirty(); - } - - m_parent.set_as_dirty(); - processed = 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 || m_current == Cut) - && 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 || m_current == Cut) - && 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_current == Cut) - && !m_parent.is_mouse_dragging() - && gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down)) { - // 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 - 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(); - // BBS - //wxGetApp().obj_manipul()->set_dirty(); - processed = true; - } - else if (evt.RightUp() && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut) - && !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(); - // BBS - //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(); - try { - if ((int)m_hover >= 0 && (int)m_hover < m_gizmos.size()) { - std::string name = get_name_from_gizmo_etype(m_hover); - int count = m_gizmos[m_hover]->get_count(); - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) { - agent->track_update_property(name, std::to_string(count)); - } - } - } - catch (...) {} - } - } - 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; + } else if (mouse_event.RightDown()) { + mc.right = true; + return true; + } else if (mouse_event.MiddleDown()) { + mc.middle = true; return true; } } - return processed; + 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; + } + + // 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; +} + +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) @@ -1549,43 +1353,26 @@ bool GLGizmosManager::generate_icons_texture() 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); - // BBS - wxGetApp().obj_list()->select_object_item((EType) idx <= Scale || (EType) idx == Text); - } -} - -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 @@ -1596,30 +1383,34 @@ bool GLGizmosManager::activate_gizmo(EType type) old_gizmo.unregister_raycasters_for_picking(); - 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. + } new_gizmo.register_raycasters_for_picking(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 02a88e6157..23812c8dca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -129,24 +129,10 @@ private: GizmoObjectManipulation m_object_manipulation; 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; @@ -155,6 +141,15 @@ private: std::map icon_list; bool m_is_dark = false; + + /// + /// 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: std::unique_ptr m_assemble_view_data; @@ -232,7 +227,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(); void update_assemble_view_data(); @@ -248,13 +242,9 @@ 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); @@ -275,8 +265,6 @@ public: return nullptr; } - Vec3d get_flattening_normal() const; - void set_flattening_data(const ModelObject* model_object); //void set_sla_support_data(ModelObject* model_object); @@ -302,8 +290,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); @@ -329,8 +317,7 @@ private: bool generate_icons_texture(); - 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; };