diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index acf0a98852..76fae46645 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3194,30 +3194,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.set_start_position_3D_as_invalid(); m_mouse.position = pos.cast(); - if (evt.Dragging() && current_printer_technology() == ptFFF && fff_print()->config().complete_objects) { - switch (m_gizmos.get_current_type()) - { - case GLGizmosManager::EType::Move: - case GLGizmosManager::EType::Scale: - case GLGizmosManager::EType::Rotate: - { - update_sequential_clearance(); - break; - } - default: { break; } - } - } - else if (evt.Dragging()) { - switch (m_gizmos.get_current_type()) - { - case GLGizmosManager::EType::Move: - case GLGizmosManager::EType::Scale: - case GLGizmosManager::EType::Rotate: - { - show_sinking_contours(); - break; - } - default: { break; } + // It should be detection of volume change + // Not only detection of some modifiers !!! + if (evt.Dragging()) { + GLGizmosManager::EType c = m_gizmos.get_current_type(); + if (current_printer_technology() == ptFFF && + fff_print()->config().complete_objects){ + if (c == GLGizmosManager::EType::Move || + c == GLGizmosManager::EType::Scale || + c == GLGizmosManager::EType::Rotate ) + update_sequential_clearance(); + } else { + if (c == GLGizmosManager::EType::Move || + c == GLGizmosManager::EType::Scale || + c == GLGizmosManager::EType::Rotate) + show_sinking_contours(); } } @@ -3844,15 +3835,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 a3c302baef..48fef56110 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -793,7 +793,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 e0e018a13c..b9ca111837 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 { @@ -74,63 +76,19 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u , m_first_input_window_render(true) , m_dirty(false) { - m_base_color = DEFAULT_BASE_COLOR; - m_drag_color = DEFAULT_DRAG_COLOR; - m_highlight_color = DEFAULT_HIGHLIGHT_COLOR; } 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 + assert(!m_dragging); -void GLGizmoBase::enable_grabber(unsigned int id) -{ - if (id < m_grabbers.size()) - m_grabbers[id].enabled = true; - - on_enable_grabber(id); -} - -void GLGizmoBase::disable_grabber(unsigned int id) -{ - if (id < m_grabbers.size()) - m_grabbers[id].enabled = false; - - on_disable_grabber(id); -} - -void GLGizmoBase::start_dragging() -{ - m_dragging = true; - - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - m_grabbers[i].dragging = (m_hover_id == i); - } - - on_start_dragging(); -} - -void GLGizmoBase::stop_dragging() -{ - m_dragging = false; - - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - m_grabbers[i].dragging = false; - } - - on_stop_dragging(); -} - -void GLGizmoBase::update(const UpdateData& data) -{ - if (m_hover_id != -1) - on_update(data); + // 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(); } bool GLGizmoBase::update_items_state() @@ -138,7 +96,7 @@ bool GLGizmoBase::update_items_state() bool res = m_dirty; m_dirty = false; return res; -}; +} ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const { @@ -189,6 +147,114 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const #endif // ENABLE_GLBEGIN_GLEND_REMOVAL } +// help function to process grabbers +// call start_dragging, stop_dragging, on_dragging +bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) { + bool is_dragging_finished = false; + if (mouse_event.Moving()) { + // it should not happen but for sure + assert(!m_dragging); + if (m_dragging) is_dragging_finished = true; + else return false; + } + + if (mouse_event.LeftDown()) { + Selection &selection = m_parent.get_selection(); + if (!selection.is_empty() && m_hover_id != -1 && + (m_grabbers.empty() || m_hover_id < static_cast(m_grabbers.size()))) { + // TODO: investigate if it is neccessary -> there was no stop dragging + selection.start_dragging(); + + m_dragging = true; + for (auto &grabber : m_grabbers) grabber.dragging = false; + if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size())) + m_grabbers[m_hover_id].dragging = true; + + // prevent change of hover_id during dragging + m_parent.set_mouse_as_dragging(); + on_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) { + // when mouse cursor leave window than finish actual dragging operation + bool is_leaving = mouse_event.Leaving(); + if (mouse_event.Dragging()) { + m_parent.set_mouse_as_dragging(); + Point mouse_coord(mouse_event.GetX(), mouse_event.GetY()); + auto ray = m_parent.mouse_ray(mouse_coord); + UpdateData data(ray, mouse_coord); + + on_dragging(data); + + wxGetApp().obj_manipul()->set_dirty(); + m_parent.set_as_dirty(); + return true; + } + else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) { +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED + do_stop_dragging(is_leaving); +#else + for (auto &grabber : m_grabbers) grabber.dragging = false; + m_dragging = false; + + // NOTE: This should be part of GLCanvas3D + // Reset hover_id when leave window + if (is_leaving) m_parent.mouse_up_cleanup(); + + on_stop_dragging(); + + // There is prediction that after draggign, data are changed + // Data are updated twice also by canvas3D::reload_scene. + // Should be fixed. + 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(); +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + return true; + } + } + return false; +} + +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED +void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup) +{ + for (auto& grabber : m_grabbers) grabber.dragging = false; + m_dragging = false; + + // NOTE: This should be part of GLCanvas3D + // Reset hover_id when leave window + if (perform_mouse_cleanup) m_parent.mouse_up_cleanup(); + + on_stop_dragging(); + + // There is prediction that after draggign, data are changed + // Data are updated twice also by canvas3D::reload_scene. + // Should be fixed. + 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(); +} +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + 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 99050a2525..2ac69d4fd7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -10,6 +10,7 @@ #include class wxWindow; +class wxMouseEvent; namespace Slic3r { @@ -29,7 +30,6 @@ class ImGuiWrapper; class GLCanvas3D; enum class CommonGizmosDataID; class CommonGizmosDataPool; -class Selection; class GLGizmoBase { @@ -85,28 +85,22 @@ public: protected: GLCanvas3D& m_parent; - - int m_group_id; + int m_group_id; // TODO: remove only for rotate EState m_state; int m_shortcut_key; std::string m_icon_filename; unsigned int m_sprite_id; int m_hover_id; bool m_dragging; - ColorRGBA m_base_color; - ColorRGBA m_drag_color; - ColorRGBA m_highlight_color; mutable std::vector m_grabbers; ImGuiWrapper* m_imgui; bool m_first_input_window_render; - mutable std::string m_tooltip; CommonGizmosDataPool* m_c; - public: GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - virtual ~GLGizmoBase() {} + virtual ~GLGizmoBase() = default; bool init() { return on_init(); } @@ -115,9 +109,6 @@ public: std::string get_name(bool include_shortcut = true) const; - int get_group_id() const { return m_group_id; } - void set_group_id(int id) { m_group_id = id; } - EState get_state() const { return m_state; } void set_state(EState state) { m_state = state; on_set_state(); } @@ -139,27 +130,33 @@ public: int get_hover_id() const { return m_hover_id; } void set_hover_id(int id); - void set_highlight_color(const ColorRGBA& color) { m_highlight_color = color; } - - void enable_grabber(unsigned int id); - void disable_grabber(unsigned int id); - - void start_dragging(); - void stop_dragging(); - bool is_dragging() const { return m_dragging; } - void update(const UpdateData& data); - // returns True when Gizmo changed its state bool update_items_state(); - void render() { m_tooltip.clear(); on_render(); } + void render() { on_render(); } void render_for_picking() { on_render_for_picking(); } void render_input_window(float x, float y, float bottom_limit); + /// + /// Mouse tooltip text + /// + /// Text to be visible in mouse tooltip virtual std::string get_tooltip() const { return ""; } + /// + /// Is called when data (Selection) is changed + /// + virtual void data_changed(){}; + + /// + /// 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. + virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; } protected: virtual bool on_init() = 0; virtual void on_load(cereal::BinaryInputArchive& ar) {} @@ -172,9 +169,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) {} @@ -191,6 +191,20 @@ protected: // Mark gizmo as dirty to Re-Render when idle() void set_dirty(); + + /// + /// function which + /// Set up m_dragging and call functions + /// on_start_dragging / on_dragging / on_stop_dragging + /// + /// Keep information about mouse click + /// same as on_mouse + bool use_grabbers(const wxMouseEvent &mouse_event); + +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED + void do_stop_dragging(bool perform_mouse_cleanup); +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + 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 ff5d89f5eb..e020b882ae 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(); @@ -53,7 +58,7 @@ std::string GLGizmoCut::on_get_name() const void GLGizmoCut::on_set_state() { // Reset m_cut_z on gizmo activation - if (get_state() == On) + if (m_state == On) m_cut_z = bounding_box().center().z(); } @@ -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() @@ -105,11 +110,15 @@ void GLGizmoCut::on_render() GLShaderProgram* shader = wxGetApp().get_shader("flat"); if (shader != nullptr) { shader->start_using(); + Vec3d diff = plane_center - m_old_center; + // Z changed when move with cut plane + // X and Y changed when move with cutted object + bool is_changed = std::abs(diff.x()) > EPSILON || + std::abs(diff.y()) > EPSILON || + std::abs(diff.z()) > EPSILON; + m_old_center = plane_center; - const bool z_changed = std::abs(plane_center.z() - m_old_z) > EPSILON; - m_old_z = plane_center.z(); - - if (!m_plane.is_initialized() || z_changed) { + if (!m_plane.is_initialized() || is_changed) { m_plane.reset(); GLModel::Geometry init_data; @@ -154,7 +163,7 @@ void GLGizmoCut::on_render() glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); #if ENABLE_GLBEGIN_GLEND_REMOVAL - if (!m_grabber_connection.is_initialized() || z_changed) { + if (!m_grabber_connection.is_initialized() || is_changed) { m_grabber_connection.reset(); GLModel::Geometry init_data; @@ -329,6 +338,8 @@ BoundingBoxf3 GLGizmoCut::bounding_box() const BoundingBoxf3 ret; const Selection& selection = m_parent.get_selection(); const Selection::IndicesList& idxs = selection.get_volume_idxs(); + return selection.get_bounding_box(); + for (unsigned int i : idxs) { const GLVolume* volume = selection.get_volume(i); if (!volume->is_modifier) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index ccf8732cf9..feb23bf450 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -8,6 +8,7 @@ namespace Slic3r { namespace GUI { +class Selection; class GLGizmoCut : public GLGizmoBase { @@ -25,7 +26,7 @@ class GLGizmoCut : public GLGizmoBase #if ENABLE_GLBEGIN_GLEND_REMOVAL GLModel m_plane; GLModel m_grabber_connection; - float m_old_z{ 0.0f }; + Vec3d m_old_center; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL struct CutContours @@ -50,6 +51,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); } @@ -58,7 +66,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 ea15deb169..e0a583f0b3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -21,9 +21,52 @@ static const Slic3r::ColorRGBA DEFAULT_HOVER_PLANE_COLOR = { 0.9f, 0.9f, 0.9f, 0 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; + return false; + } + if (mouse_event.LeftDown()) { + if (m_hover_id != -1) { + m_mouse_left_down = true; + 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")); + } + return true; + } + + // fix: prevent restart gizmo when reselect object + // take responsibility for left up + if (m_parent.get_first_hover_volume_idx() >= 0) m_mouse_left_down = true; + + } else if (mouse_event.LeftUp()) { + if (m_mouse_left_down) { + // responsible for mouse left up after selecting plane + m_mouse_left_down = false; + return true; + } + } else if (mouse_event.Leaving()) { + m_mouse_left_down = false; + } + return false; +} + +void GLGizmoFlatten::data_changed() +{ + const Selection & selection = m_parent.get_selection(); + const ModelObject *model_object = nullptr; + if (selection.is_single_full_instance() || + selection.is_from_single_object() ) { + model_object = selection.get_model()->objects[selection.get_object_idx()]; + } + set_flattening_data(model_object); } bool GLGizmoFlatten::on_init() @@ -53,15 +96,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(); @@ -149,7 +183,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; @@ -415,13 +448,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 3a3a904343..f256dfe7ef 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -22,7 +22,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() @@ -42,8 +41,8 @@ private: Vec3d m_first_instance_mirror; std::vector m_planes; + bool m_mouse_left_down = false; // for detection left_up of this gizmo bool m_planes_valid = false; - mutable Vec3d m_starting_center; const ModelObject* m_old_model_object = nullptr; std::vector instances_matrices; @@ -54,17 +53,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; + void data_changed() 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 be52ebcb9a..f3ea526a09 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -42,7 +42,7 @@ bool GLGizmoHollow::on_init() return true; } -void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&) +void GLGizmoHollow::data_changed() { if (! m_c->selection_info()) return; @@ -417,20 +417,70 @@ 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(); + + static bool pending_right_up = false; + if (mouse_event.LeftDown()) { + bool control_down = mouse_event.CmdDown(); + bool grabber_contains_mouse = (get_hover_id() != -1); + 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; + } else if (mouse_event.Dragging()) { + if (m_parent.get_move_volume_id() != -1) + // don't allow dragging objects with the Sla gizmo on + return true; + + bool control_down = mouse_event.CmdDown(); + if (control_down) { + // 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()) { + pending_right_up = false; + } + } else if(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.LeftUp()) { + if (!m_parent.is_mouse_dragging()) { + bool control_down = mouse_event.CmdDown(); + // in case 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.RightDown()) { + if (m_parent.get_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; + } + } else if (mouse_event.RightUp()) { + if (pending_right_up) { + pending_right_up = false; + return true; + } } + return false; } - void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) { wxGetApp().CallAfter([this, postpone_error_messages]() { @@ -820,6 +870,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 fa89e0febc..feab896cc5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -19,7 +19,7 @@ class ConfigOptionDef; namespace GUI { enum class SLAGizmoEventType : unsigned char; - +class Selection; class GLGizmoHollow : public GLGizmoBase { private: @@ -29,16 +29,22 @@ private: public: GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoHollow() = default; - void set_sla_support_data(ModelObject* model_object, const Selection& selection); + void data_changed() override; bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); void delete_selected_points(); 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; @@ -94,6 +100,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/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index dd9cf0de2e..24e90fceb1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -146,10 +146,9 @@ void GLGizmoMmuSegmentation::render_painter_gizmo() glsafe(::glDisable(GL_BLEND)); } -void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) +void GLGizmoMmuSegmentation::data_changed() { - GLGizmoPainterBase::set_painter_gizmo_data(selection); - + GLGizmoPainterBase::data_changed(); if (m_state != On || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptFFF || wxGetApp().extruders_edited_cnt() <= 1) return; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index c294fafcf2..6f357bb6f1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -87,7 +87,7 @@ public: void render_painter_gizmo() override; - void set_painter_gizmo_data(const Selection& selection) override; + void data_changed() override; void render_triangles(const Selection& selection) const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 78262da716..9aff7e945b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -46,6 +46,14 @@ std::string GLGizmoMove3D::get_tooltip() const #endif // ENABLE_WORLD_COORDINATE } +bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) { + return use_grabbers(mouse_event); +} + +void GLGizmoMove3D::data_changed() { + m_grabbers[2].enabled = !m_parent.get_selection().is_wipe_tower(); +} + bool GLGizmoMove3D::on_init() { for (int i = 0; i < 3; ++i) { @@ -69,40 +77,41 @@ bool GLGizmoMove3D::on_is_activable() const void GLGizmoMove3D::on_start_dragging() { - if (m_hover_id != -1) { - m_displacement = Vec3d::Zero(); + assert(m_hover_id != -1); + + m_displacement = Vec3d::Zero(); #if ENABLE_WORLD_COORDINATE - const Selection& selection = m_parent.get_selection(); - const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); - if (coordinates_type == ECoordinatesType::World) - m_starting_drag_position = m_center + m_grabbers[m_hover_id].center; - else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { - const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); - m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation()) * m_grabbers[m_hover_id].center; - } - else { - const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); - m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * m_grabbers[m_hover_id].center; - } - m_starting_box_center = m_center; - m_starting_box_bottom_center = m_center; - m_starting_box_bottom_center.z() = m_bounding_box.min.z(); -#else - 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.z() = box.min.z(); -#endif // ENABLE_WORLD_COORDINATE + const Selection& selection = m_parent.get_selection(); + const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (coordinates_type == ECoordinatesType::World) + m_starting_drag_position = m_center + m_grabbers[m_hover_id].center; + else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation()) * m_grabbers[m_hover_id].center; } + else { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * m_grabbers[m_hover_id].center; + } + m_starting_box_center = m_center; + m_starting_box_bottom_center = m_center; + m_starting_box_bottom_center.z() = m_bounding_box.min.z(); +#else + 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.z() = box.min.z(); +#endif // ENABLE_WORLD_COORDINATE } 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); @@ -110,6 +119,13 @@ 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(); +#if ENABLE_WORLD_COORDINATE + selection.translate(m_displacement, wxGetApp().obj_manipul()->get_coordinates_type()); +#else + selection.translate(m_displacement); +#endif // ENABLE_WORLD_COORDINATE } void GLGizmoMove3D::on_render() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index b167e80695..b729211b11 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -7,6 +7,10 @@ namespace Slic3r { namespace GUI { +#if ENABLE_WORLD_COORDINATE +class Selection; +#endif // ENABLE_WORLD_COORDINATE + class GLGizmoMove3D : public GLGizmoBase { static const double Offset; @@ -38,19 +42,28 @@ 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; + + /// + /// Detect reduction of move for wipetover on selection change + /// + void data_changed() 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 82a816d1b9..d3fd294b3e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -40,13 +40,13 @@ GLGizmoPainterBase::~GLGizmoPainterBase() #endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } -void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection) +void GLGizmoPainterBase::data_changed() { if (m_state != On) return; const ModelObject* mo = m_c->selection_info() ? m_c->selection_info()->model_object() : nullptr; - + const Selection & selection = m_parent.get_selection(); if (mo && selection.is_from_single_instance() && (m_schedule_update || mo->id() != m_old_mo_id || mo->volumes.size() != m_old_volumes_size)) { @@ -641,7 +641,72 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous return false; } +bool GLGizmoPainterBase::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(); + if (mouse_event.Moving()) { + gizmo_event(SLAGizmoEventType::Moving, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), false); + return 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()) { + 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; + } else if (mouse_event.RightDown()){ + if (!control_down && selected_object_idx != -1 && + gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) + // event was taken care of + return true; + } else if (mouse_event.Dragging()) { + if (m_parent.get_move_volume_id() != -1) + // don't allow dragging objects with the Sla gizmo on + return true; + if (!control_down && 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; + } + if(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); + return false; + } + } else if (mouse_event.LeftUp()) { + if (!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()) { + if (!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 37c7163e2f..7949e26572 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -25,6 +25,7 @@ enum class SLAGizmoEventType : unsigned char; class ClippingPlane; struct Camera; class GLGizmoMmuSegmentation; +class Selection; enum class PainterGizmoType { FDM_SUPPORTS, @@ -135,8 +136,8 @@ private: void on_render_for_picking() override {} public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - virtual ~GLGizmoPainterBase() override; - virtual void set_painter_gizmo_data(const Selection& selection); + ~GLGizmoPainterBase() override; + void data_changed() override; virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); // Following function renders the triangles and cursor. Having this separated @@ -149,6 +150,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(); @@ -257,9 +267,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 8646b05e44..693f1f4ec5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -31,7 +31,23 @@ const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) : GLGizmoBase(parent, "", -1) , m_axis(axis) -{} + , m_angle(0.0) + , m_center(0.0, 0.0, 0.0) + , m_radius(0.0f) + , m_snap_coarse_in_radius(0.0f) + , m_snap_coarse_out_radius(0.0f) + , m_snap_fine_in_radius(0.0f) + , m_snap_fine_out_radius(0.0f) + , m_drag_color(DEFAULT_DRAG_COLOR) + , m_highlight_color(DEFAULT_HIGHLIGHT_COLOR) +{ + m_group_id = static_cast(axis); +} + +void GLGizmoRotate::set_highlight_color(const ColorRGBA &color) +{ + m_highlight_color = color; +} void GLGizmoRotate::set_angle(double angle) { @@ -53,6 +69,28 @@ std::string GLGizmoRotate::get_tooltip() const return (m_hover_id == 0 || m_grabbers.front().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); } + +void GLGizmoRotate::start_dragging() +{ + m_grabbers[0].dragging = true; + on_start_dragging(); +} + +void GLGizmoRotate::stop_dragging() +{ + m_grabbers[0].dragging = false; + on_stop_dragging(); +} + +void GLGizmoRotate::enable_grabber() { m_grabbers[0].enabled = true; } +void GLGizmoRotate::disable_grabber() { m_grabbers[0].enabled = false; } + bool GLGizmoRotate::on_init() { m_grabbers.push_back(Grabber()); @@ -74,7 +112,7 @@ void GLGizmoRotate::on_start_dragging() #endif // ENABLE_WORLD_COORDINATE } -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())); @@ -697,25 +735,60 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) - , m_gizmos({ GLGizmoRotate(parent, GLGizmoRotate::X), GLGizmoRotate(parent, GLGizmoRotate::Y), GLGizmoRotate(parent, GLGizmoRotate::Z) }) -{ - for (unsigned int i = 0; i < 3; ++i) { - m_gizmos[i].set_group_id(i); - } + , m_gizmos({ + GLGizmoRotate(parent, GLGizmoRotate::X), + GLGizmoRotate(parent, GLGizmoRotate::Y), + GLGizmoRotate(parent, GLGizmoRotate::Z) }) +{} - load_rotoptimize_state(); +bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event) +{ + if (mouse_event.Dragging() && m_dragging) { + // Apply new temporary rotations +#if ENABLE_WORLD_COORDINATE + TransformationType transformation_type; + switch (wxGetApp().obj_manipul()->get_coordinates_type()) + { + default: + case ECoordinatesType::World: { transformation_type = TransformationType::World_Relative_Joint; break; } + case ECoordinatesType::Instance: { transformation_type = TransformationType::Instance_Relative_Joint; break; } + case ECoordinatesType::Local: { transformation_type = TransformationType::Local_Relative_Joint; break; } + } +#else + TransformationType transformation_type(TransformationType::World_Relative_Joint); +#endif // ENABLE_WORLD_COORDINATE + if (mouse_event.AltDown()) transformation_type.set_independent(); + m_parent.get_selection().rotate(get_rotation(), transformation_type); + } + return use_grabbers(mouse_event); +} + +void GLGizmoRotate3D::data_changed() { + const Selection &selection = m_parent.get_selection(); + bool is_wipe_tower = selection.is_wipe_tower(); + if (is_wipe_tower) { + DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + float wipe_tower_rotation_angle = + dynamic_cast( + config.option("wipe_tower_rotation_angle")) + ->value; + set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle)); + m_gizmos[0].disable_grabber(); + m_gizmos[1].disable_grabber(); + } else { + set_rotation(Vec3d::Zero()); + m_gizmos[0].enable_grabber(); + m_gizmos[1].enable_grabber(); + } } 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; @@ -734,14 +807,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 92aed92e92..7b53e226a4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -5,7 +5,7 @@ namespace Slic3r { namespace GUI { - +class Selection; class GLGizmoRotate : public GLGizmoBase { static const float Offset; @@ -20,9 +20,9 @@ class GLGizmoRotate : public GLGizmoBase public: enum Axis : unsigned char { - X, - Y, - Z + X=0, + Y=1, + Z=2 }; private: @@ -56,6 +56,8 @@ private: float m_old_hover_radius{ 0.0f }; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + ColorRGBA m_drag_color; + ColorRGBA m_highlight_color; public: GLGizmoRotate(GLCanvas3D& parent, Axis axis); virtual ~GLGizmoRotate() = default; @@ -65,11 +67,27 @@ public: std::string get_tooltip() const override; + void start_dragging(); + void stop_dragging(); + + void enable_grabber(); + void disable_grabber(); + + void set_highlight_color(const ColorRGBA &color); + + /// + /// 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; @@ -119,6 +137,14 @@ 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; + + void data_changed() override; protected: bool on_init() override; std::string on_get_name() const override; @@ -132,20 +158,17 @@ protected: } void on_enable_grabber(unsigned int id) override { if (id < 3) - m_gizmos[id].enable_grabber(0); + m_gizmos[id].enable_grabber(); } void on_disable_grabber(unsigned int id) override { if (id < 3) - m_gizmos[id].disable_grabber(0); + m_gizmos[id].disable_grabber(); } 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 { for (GLGizmoRotate& g : m_gizmos) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index bd7cda47e3..5efc1e1b4b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -8,7 +8,7 @@ #include -#include +#include namespace Slic3r { namespace GUI { @@ -18,6 +18,12 @@ const double GLGizmoScale3D::Offset = 5.0; GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) + , m_scale(Vec3d::Ones()) + , m_offset(Vec3d::Zero()) + , m_snap_step(0.05) + , m_base_color(DEFAULT_BASE_COLOR) + , m_drag_color(DEFAULT_DRAG_COLOR) + , m_highlight_color(DEFAULT_HIGHLIGHT_COLOR) { #if ENABLE_GLBEGIN_GLEND_REMOVAL m_grabber_connections[0].grabber_indices = { 0, 1 }; @@ -62,6 +68,84 @@ std::string GLGizmoScale3D::get_tooltip() const return ""; } +bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event) +{ + if (mouse_event.Dragging()) { + if (m_dragging) { +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED + int res = 1; + if (m_scale.x() != m_scale.y() || m_scale.x() != m_scale.z()) + res = m_parent.get_selection().bake_transform_if_needed(); + + if (res != 1) { + do_stop_dragging(true); + return true; + } + else { +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + // Apply new temporary scale factors +#if ENABLE_WORLD_COORDINATE + TransformationType transformation_type; + if (!wxGetApp().obj_manipul()->is_world_coordinates()) + transformation_type.set_local(); +#else + TransformationType transformation_type(TransformationType::Local_Absolute_Joint); +#endif // ENABLE_WORLD_COORDINATE + if (mouse_event.AltDown()) transformation_type.set_independent(); + + Selection &selection = m_parent.get_selection(); + selection.scale(m_scale, transformation_type); +#if ENABLE_WORLD_COORDINATE + if (mouse_event.CmdDown()) selection.translate(m_offset, wxGetApp().obj_manipul()->get_coordinates_type()); +#else + if (mouse_event.CmdDown()) selection.translate(m_offset, true); +#endif // ENABLE_WORLD_COORDINATE +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED + } +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + } + } + return use_grabbers(mouse_event); +} + +void GLGizmoScale3D::data_changed() +{ + const Selection &selection = m_parent.get_selection(); +#if ENABLE_WORLD_COORDINATE +#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED + bool enable_scale_xyz = !selection.requires_uniform_scale(); +#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED +#else + bool enable_scale_xyz = selection.is_single_full_instance() || + selection.is_single_volume() || + selection.is_single_modifier(); +#endif // ENABLE_WORLD_COORDINATE +#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED + if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) { +#else + for (unsigned int i = 0; i < 6; ++i) + m_grabbers[i].enabled = enable_scale_xyz; + + if (enable_scale_xyz) { +#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED + + // all volumes in the selection belongs to the same instance, any of + // them contains the needed data, so we take the first + const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); + if (selection.is_single_full_instance()) + set_scale(volume->get_instance_scaling_factor()); +#if ENABLE_WORLD_COORDINATE + else if (selection.is_single_volume_or_modifier()) +#else + else if (selection.is_single_volume() || + selection.is_single_modifier()) +#endif // ENABLE_WORLD_COORDINATE + set_scale(volume->get_volume_scaling_factor()); + } + else + set_scale(Vec3d::Ones()); +} + bool GLGizmoScale3D::on_init() { for (int i = 0; i < 10; ++i) { @@ -98,29 +182,32 @@ bool GLGizmoScale3D::on_is_activable() const void GLGizmoScale3D::on_start_dragging() { - if (m_hover_id != -1) { - m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); + assert(m_hover_id != -1); + m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); #if ENABLE_WORLD_COORDINATE - m_starting.drag_position = m_grabbers_transform * m_grabbers[m_hover_id].center; - m_starting.box = m_bounding_box; - m_starting.center = m_center; - m_starting.instance_center = m_instance_center; + m_starting.drag_position = m_grabbers_transform * m_grabbers[m_hover_id].center; + m_starting.box = m_bounding_box; + m_starting.center = m_center; + m_starting.instance_center = m_instance_center; #else - m_starting.drag_position = m_grabbers[m_hover_id].center; - m_starting.box = (m_starting.ctrl_down && m_hover_id < 6) ? m_bounding_box : m_parent.get_selection().get_bounding_box(); + m_starting.drag_position = m_grabbers[m_hover_id].center; + 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()); #endif // ENABLE_WORLD_COORDINATE - } } -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 41efbe5758..2d07d9435d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -3,11 +3,17 @@ #include "GLGizmoBase.hpp" +#if !ENABLE_WORLD_COORDINATE #include "libslic3r/BoundingBox.hpp" +#endif // !ENABLE_WORLD_COORDINATE namespace Slic3r { namespace GUI { +#if ENABLE_WORLD_COORDINATE +class Selection; +#endif // ENABLE_WORLD_COORDINATE + class GLGizmoScale3D : public GLGizmoBase { static const double Offset; @@ -53,6 +59,9 @@ class GLGizmoScale3D : public GLGizmoBase std::array m_grabber_connections; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + ColorRGBA m_base_color; + ColorRGBA m_drag_color; + ColorRGBA m_highlight_color; public: GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); @@ -62,20 +71,23 @@ public: const Vec3d& get_scale() const { return m_scale; } void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; } -#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED - const Vec3d& get_starting_scale() const { return m_starting.scale; } -#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED - - 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; + + void data_changed() 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 fa0b27269a..3a503407ce 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -28,9 +28,7 @@ namespace GUI { GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) -{ -} - +{} bool GLGizmoSlaSupports::on_init() { @@ -48,11 +46,15 @@ bool GLGizmoSlaSupports::on_init() m_desc["manual_editing"] = _L("Manual editing"); m_desc["clipping_of_view"] = _L("Clipping of view")+ ": "; m_desc["reset_direction"] = _L("Reset direction"); + + m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24)); + m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.)); + m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.)); return true; } -void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection) +void GLGizmoSlaSupports::data_changed() { if (! m_c->selection_info()) return; @@ -553,22 +555,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; @@ -985,7 +971,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) { @@ -1122,6 +1122,61 @@ 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(); + + static bool pending_right_up = false; + if (mouse_event.LeftDown()) { + bool grabber_contains_mouse = (get_hover_id() != -1); + bool control_down = mouse_event.CmdDown(); + if ((!control_down || grabber_contains_mouse) && + gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), false)) + return true; + } else if (mouse_event.Dragging()) { + bool control_down = mouse_event.CmdDown(); + if (m_parent.get_move_volume_id() != -1) { + // don't allow dragging objects with the Sla gizmo on + return true; + } else if (!control_down && + 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 (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()) + pending_right_up = false; + } + } else if (mouse_event.LeftUp() && !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(), mouse_event.CmdDown()); + return true; + }else if (mouse_event.RightDown()){ + if (m_parent.get_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; + } + } else 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 49df659f48..5eb29823ee 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -16,7 +16,7 @@ namespace Slic3r { class ConfigOption; namespace GUI { - +class Selection; enum class SLAGizmoEventType : unsigned char; class GLGizmoSlaSupports : public GLGizmoBase @@ -57,7 +57,7 @@ private: public: GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoSlaSupports() = default; - void set_sla_support_data(ModelObject* model_object, const Selection& selection); + void data_changed() override; bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); void delete_selected_points(bool force = false); //ClippingPlane get_sla_clipping_plane() const; @@ -70,10 +70,15 @@ 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; @@ -107,7 +112,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, @@ -130,13 +134,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 40cdb9bbda..88159cbb8b 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; @@ -161,9 +163,9 @@ void GLGizmosManager::refresh_on_off_state() if (m_serializing || m_current == Undefined || m_gizmos.empty()) return; - if (m_current != Undefined - && ! m_gizmos[m_current]->is_activable() && activate_gizmo(Undefined)) - update_data(); + // FS: Why update data after Undefined gizmo activation? + if (!m_gizmos[m_current]->is_activable() && activate_gizmo(Undefined)) + update_data(); } void GLGizmosManager::reset_all_states() @@ -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; } @@ -208,94 +214,14 @@ void GLGizmosManager::set_hover_id(int id) m_gizmos[m_current]->set_hover_id(id); } -void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable) -{ - if (!m_enabled || type == Undefined || m_gizmos.empty()) - return; - - if (enable) - m_gizmos[type]->enable_grabber(id); - else - 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_data() { - if (!m_enabled) - return; - - const Selection& selection = m_parent.get_selection(); - - bool is_wipe_tower = selection.is_wipe_tower(); - enable_grabber(Move, 2, !is_wipe_tower); - enable_grabber(Rotate, 0, !is_wipe_tower); - enable_grabber(Rotate, 1, !is_wipe_tower); - -#if ENABLE_WORLD_COORDINATE -#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED - bool enable_scale_xyz = !selection.requires_uniform_scale(); -#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED -#else - bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); -#endif // ENABLE_WORLD_COORDINATE -#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED - for (unsigned int i = 0; i < 6; ++i) { - enable_grabber(Scale, i, enable_scale_xyz); - } -#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED - + if (!m_enabled) return; if (m_common_gizmos_data) m_common_gizmos_data->update(get_current() ? get_current()->get_requirements() : CommonGizmosDataID(0)); - - if (selection.is_single_full_instance()) { - // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - set_scale(volume->get_instance_scaling_factor()); - set_rotation(Vec3d::Zero()); - ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()]; - set_flattening_data(model_object); - set_sla_support_data(model_object); - set_painter_gizmo_data(); - } -#if ENABLE_WORLD_COORDINATE - else if (selection.is_single_volume_or_modifier()) { -#else - else if (selection.is_single_volume() || selection.is_single_modifier()) { -#endif // ENABLE_WORLD_COORDINATE - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - set_scale(volume->get_volume_scaling_factor()); - set_rotation(Vec3d::Zero()); - set_flattening_data(nullptr); - set_sla_support_data(nullptr); - set_painter_gizmo_data(); - } - else if (is_wipe_tower) { - DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config; - set_scale(Vec3d::Ones()); - set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast(config.option("wipe_tower_rotation_angle"))->value)); - set_flattening_data(nullptr); - set_sla_support_data(nullptr); - set_painter_gizmo_data(); - } - else { - set_scale(Vec3d::Ones()); - set_rotation(Vec3d::Zero()); - set_flattening_data(selection.is_from_single_object() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); - set_sla_support_data(selection.is_from_single_instance() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); - set_painter_gizmo_data(); - } + if (m_current != Undefined) m_gizmos[m_current]->data_changed(); } bool GLGizmosManager::is_running() const @@ -335,117 +261,6 @@ bool GLGizmosManager::is_dragging() const return m_gizmos[m_current]->is_dragging(); } -void GLGizmosManager::start_dragging() -{ - if (! m_enabled || m_current == Undefined) - return; - m_gizmos[m_current]->start_dragging(); -} - -void GLGizmosManager::stop_dragging() -{ - if (! m_enabled || m_current == Undefined) - return; - - 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) - return Vec3d::Ones(); - - return dynamic_cast(m_gizmos[Scale].get())->get_scale(); -} - -void GLGizmosManager::set_scale(const Vec3d& scale) -{ - if (!m_enabled || m_gizmos.empty()) - return; - - dynamic_cast(m_gizmos[Scale].get())->set_scale(scale); -} - -#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED -Vec3d GLGizmosManager::get_starting_scale() const -{ - if (!m_enabled) - return Vec3d::Ones(); - - return dynamic_cast(m_gizmos[Scale].get())->get_starting_scale(); -} -#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED - -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()) - return Vec3d::Zero(); - - return dynamic_cast(m_gizmos[Rotate].get())->get_rotation(); -} - -void GLGizmosManager::set_rotation(const Vec3d& rotation) -{ - if (!m_enabled || m_gizmos.empty()) - return; - 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()) - return; - - dynamic_cast(m_gizmos[Flatten].get())->set_flattening_data(model_object); -} - -void GLGizmosManager::set_sla_support_data(ModelObject* model_object) -{ - if (! m_enabled - || m_gizmos.empty() - || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA) - return; - - auto* gizmo_hollow = dynamic_cast(m_gizmos[Hollow].get()); - auto* gizmo_supports = dynamic_cast(m_gizmos[SlaSupports].get()); - gizmo_hollow->set_sla_support_data(model_object, m_parent.get_selection()); - gizmo_supports->set_sla_support_data(model_object, m_parent.get_selection()); -} - -void GLGizmosManager::set_painter_gizmo_data() -{ - if (!m_enabled || m_gizmos.empty()) - return; - - dynamic_cast(m_gizmos[FdmSupports].get())->set_painter_gizmo_data(m_parent.get_selection()); - dynamic_cast(m_gizmos[Seam].get())->set_painter_gizmo_data(m_parent.get_selection()); - dynamic_cast(m_gizmos[MmuSegmentation].get())->set_painter_gizmo_data(m_parent.get_selection()); -} - // Returns true if the gizmo used the event to do something, false otherwise. bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) { @@ -534,7 +349,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; @@ -547,280 +362,114 @@ 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; } - if (m_mouse_capture.right) { - processed = true; - m_mouse_capture.right = false; + else if (mouse_event.RightDown()) { + mc.right = true; + return true; } -// 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 -#if ENABLE_WORLD_COORDINATE - selection.translate(get_displacement(), wxGetApp().obj_manipul()->get_coordinates_type()); -#else - selection.translate(get_displacement()); -#endif // ENABLE_WORLD_COORDINATE - wxGetApp().obj_manipul()->set_dirty(); - break; - } - case Scale: - { -#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED - const Vec3d scale = get_scale(); - int res = 1; - if (scale.x() != scale.y() || scale.x() != scale.z()) { - // we need to release the mouse or, if the modal dialog is shown by the - // following call to bake_transform_if_needed(), the focus gets messed up - if (m_parent.get_wxglcanvas()->HasCapture()) - m_parent.get_wxglcanvas()->ReleaseMouse(); - - res = selection.bake_transform_if_needed(); - - // re-capture the mouse - if (!m_parent.get_wxglcanvas()->HasCapture()) - m_parent.get_wxglcanvas()->CaptureMouse(); - } - - if (res != 1) { - // the modal dialog has been disposed, fake mouse up - stop_dragging(); - update_data(); - m_parent.mouse_up_cleanup(); - } - else { -#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED - // Apply new temporary scale factors -#if ENABLE_WORLD_COORDINATE - TransformationType transformation_type; - if (!wxGetApp().obj_manipul()->is_world_coordinates()) - transformation_type.set_local(); -#else - TransformationType transformation_type(TransformationType::Local_Absolute_Joint); -#endif // ENABLE_WORLD_COORDINATE - if (evt.AltDown()) - transformation_type.set_independent(); - selection.scale(get_scale(), transformation_type); - if (control_down) -#if ENABLE_WORLD_COORDINATE - selection.translate(get_scale_offset(), wxGetApp().obj_manipul()->get_coordinates_type()); -#else - selection.translate(get_scale_offset(), true); -#endif // ENABLE_WORLD_COORDINATE - wxGetApp().obj_manipul()->set_dirty(); -#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED - } -#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED - break; - } - case Rotate: - { - // Apply new temporary rotations -#if ENABLE_WORLD_COORDINATE - TransformationType transformation_type; - switch (wxGetApp().obj_manipul()->get_coordinates_type()) - { - default: - case ECoordinatesType::World: { transformation_type = TransformationType::World_Relative_Joint; break; } - case ECoordinatesType::Instance: { transformation_type = TransformationType::Instance_Relative_Joint; break; } - case ECoordinatesType::Local: { transformation_type = TransformationType::Local_Absolute_Joint; break; } - } -#else - TransformationType transformation_type(TransformationType::World_Relative_Joint); -#endif // ENABLE_WORLD_COORDINATE - 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; - } - } - 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; + 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) @@ -1250,68 +899,64 @@ 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()); - GLGizmoBase* old_gizmo = m_current == Undefined ? nullptr : m_gizmos[m_current].get(); - GLGizmoBase* new_gizmo = type == Undefined ? nullptr : m_gizmos[type].get(); + // already activated + if (m_current == type) return true; - if (old_gizmo) { - old_gizmo->set_state(GLGizmoBase::Off); - if (old_gizmo->get_state() != GLGizmoBase::Off) + if (m_current != Undefined) { + // clean up previous gizmo + GLGizmoBase &old_gizmo = *m_gizmos[m_current]; + old_gizmo.set_state(GLGizmoBase::Off); + if (old_gizmo.get_state() != GLGizmoBase::Off) return false; // gizmo refused to be turned off, do nothing. - if (! m_parent.get_gizmos_manager().is_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); } - if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing() - && new_gizmo->wants_enter_leave_snapshots()) + if (type == Undefined) { + // 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) { + m_current = Undefined; + return false; // gizmo refused to be turned on. + } - if (new_gizmo) - new_gizmo->set_state(GLGizmoBase::On); + // sucessful activation of gizmo return true; } @@ -1349,11 +994,5 @@ bool GLGizmosManager::is_hiding_instances() const && m_common_gizmos_data->instances_hider()->is_valid()); } - -int GLGizmosManager::get_shortcut_key(GLGizmosManager::EType type) const -{ - return m_gizmos[type]->get_shortcut_key(); -} - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 336c2b1bb0..a987ccc239 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -112,28 +112,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); @@ -184,14 +178,15 @@ public: void refresh_on_off_state(); void reset_all_states(); - bool is_serializing() const { return m_serializing; } bool open_gizmo(EType type); bool check_gizmos_closed_except(EType) const; 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); + /// + /// Distribute information about different data into active gizmo + /// Should be called when selection changed + /// void update_data(); EType get_current_type() const { return m_current; } @@ -202,30 +197,7 @@ public: bool handle_shortcut(int key); bool is_dragging() const; - void start_dragging(); - void stop_dragging(); - Vec3d get_displacement() const; - - Vec3d get_scale() const; - void set_scale(const Vec3d& scale); -#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED - Vec3d get_starting_scale() const; -#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED - 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); - - void set_painter_gizmo_data(); - - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); ClippingPlane get_clipping_plane() const; bool wants_reslice_supports_on_undo() const; @@ -242,21 +214,26 @@ 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); void update_after_undo_redo(const UndoRedo::Snapshot& snapshot); int get_selectable_icons_cnt() const { return get_selectable_idxs().size(); } - int get_shortcut_key(GLGizmosManager::EType) const; // To end highlight set gizmo = undefined void set_highlight(EType gizmo, bool highlight_shown) { m_highlight = std::pair(gizmo, highlight_shown); } bool get_highlight_state() const { return m_highlight.second; } private: + bool gizmo_event(SLAGizmoEventType action, + const Vec2d & mouse_position = Vec2d::Zero(), + bool shift_down = false, + bool alt_down = false, + bool control_down = false); + void render_background(float left, float top, float right, float bottom, float border) const; void do_render_overlay() const; @@ -266,8 +243,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; };