diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 785f6d7ea..05f59b610 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -192,7 +192,7 @@ bool GLGizmoAdvancedCut::gizmo_event(SLAGizmoEventType action, const Vec2d &mous return false; } -bool GLGizmoAdvancedCut::on_key(wxKeyEvent &evt) +bool GLGizmoAdvancedCut::on_key(const wxKeyEvent& evt) { bool ctrl_down = evt.GetModifiers() & wxMOD_CONTROL; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index e840f26df..1753e1dd8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -211,7 +211,7 @@ public: GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); - bool on_key(wxKeyEvent &evt); + bool on_key(const wxKeyEvent &evt) override; double get_movement() const { return m_movement; } void finish_rotation(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index d517d360f..4c0b3df8d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -355,6 +355,11 @@ void GLGizmoBase::set_icon_filename(const std::string &filename) { m_icon_filename = filename; } +bool GLGizmoBase::on_key(const wxKeyEvent& key_event) +{ + return false; +} + void GLGizmoBase::set_hover_id(int id) { if (m_grabbers.empty() || (id < (int)m_grabbers.size())) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 024e26aa5..60371f095 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -214,6 +214,7 @@ public: virtual bool apply_clipping_plane() { return true; } virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; } + virtual bool on_key(const wxKeyEvent& key_event); unsigned int get_sprite_id() const { return m_sprite_id; } int get_hover_id() const { return m_hover_id; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 7b702972d..0a6581ad1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -351,8 +351,10 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const // vector from the starting position to the found intersection Vec3d inters_vec = inters - m_starting_drag_position; - // finds projection of the vector along the staring direction - projection = inters_vec.dot(starting_vec.normalized()); + projection = inters_vec.norm(); + const double sign = inters_vec.dot(starting_vec) > 1e-6f ? 1.0f : -1.0f; + + projection = projection * sign; } if (wxGetKeyState(WXK_SHIFT)) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 84c6bdc8c..67114b4f7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -118,6 +118,27 @@ BoundingBoxf3 GLGizmoScale3D::get_bounding_box() const return t_aabb; } +bool GLGizmoScale3D::on_key(const wxKeyEvent& key_event) +{ + bool b_processed = false; + if (key_event.GetEventType() == wxEVT_KEY_DOWN) { + if (key_event.GetKeyCode() == WXK_CONTROL) { + if (!is_scalling_mode_locked()) { + set_asymmetric_scalling_enable(!is_asymmetric_scalling_enabled()); + lock_scalling_mode(true); + b_processed = true; + } + } + } + else if (key_event.GetEventType() == wxEVT_KEY_UP) { + if (key_event.GetKeyCode() == WXK_CONTROL) { + lock_scalling_mode(false); + b_processed = true; + } + } + return b_processed; +} + bool GLGizmoScale3D::on_init() { for (int i = 0; i < 10; ++i) @@ -219,7 +240,7 @@ void GLGizmoScale3D::update_grabbers_data() m_instance_center = (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) ? selection.get_first_volume()->get_instance_offset() : m_center; const Vec3d box_half_size = 0.5 * m_bounding_box.size(); - bool ctrl_down = wxGetKeyState(WXK_CONTROL); + bool b_asymmetric_scalling = is_asymmetric_scalling_enabled(); bool single_instance = selection.is_single_full_instance(); @@ -227,29 +248,29 @@ void GLGizmoScale3D::update_grabbers_data() // x axis m_grabbers[0].center = Vec3d(-(box_half_size.x()), 0.0, -box_half_size.z()); - m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + m_grabbers[0].color = (b_asymmetric_scalling && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; m_grabbers[1].center = Vec3d(box_half_size.x(), 0.0, -box_half_size.z()); - m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + m_grabbers[1].color = (b_asymmetric_scalling && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; // y axis m_grabbers[2].center = Vec3d(0.0, -(box_half_size.y()), -box_half_size.z()); - m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + m_grabbers[2].color = (b_asymmetric_scalling && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; m_grabbers[3].center = Vec3d(0.0, box_half_size.y(), -box_half_size.z()); - m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + m_grabbers[3].color = (b_asymmetric_scalling && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; // z axis do not show 4 m_grabbers[4].center = Vec3d(0.0, 0.0, -(box_half_size.z())); m_grabbers[4].enabled = false; m_grabbers[5].center = Vec3d(0.0, 0.0, box_half_size.z()); - m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; + m_grabbers[5].color = (b_asymmetric_scalling && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; // uniform m_grabbers[6].center = Vec3d(-box_half_size.x(), -box_half_size.y(), -box_half_size.z()); - m_grabbers[6].color = (ctrl_down && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; + m_grabbers[6].color = (b_asymmetric_scalling && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; m_grabbers[7].center = Vec3d(box_half_size.x(), -box_half_size.y(), -box_half_size.z()); - m_grabbers[7].color = (ctrl_down && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; + m_grabbers[7].color = (b_asymmetric_scalling && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; m_grabbers[8].center = Vec3d(box_half_size.x(), box_half_size.y(), -box_half_size.z()); - m_grabbers[8].color = (ctrl_down && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; + m_grabbers[8].color = (b_asymmetric_scalling && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; m_grabbers[9].center = Vec3d(-box_half_size.x(), box_half_size.y(), -box_half_size.z()); - m_grabbers[9].color = (ctrl_down && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; + m_grabbers[9].color = (b_asymmetric_scalling && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; Transform3d t_model_matrix{ Transform3d::Identity() }; const auto t_fullsize = get_grabber_size(); @@ -279,6 +300,26 @@ void GLGizmoScale3D::change_cs_by_selection() { } } +void GLGizmoScale3D::set_asymmetric_scalling_enable(bool is_enabled) +{ + m_b_asymmetric_scalling = is_enabled; +} + +bool GLGizmoScale3D::is_asymmetric_scalling_enabled() const +{ + return m_b_asymmetric_scalling; +} + +void GLGizmoScale3D::lock_scalling_mode(bool is_locked) +{ + m_b_scalling_mode_locked = is_locked; +} + +bool GLGizmoScale3D::is_scalling_mode_locked() const +{ + return m_b_scalling_mode_locked; +} + void GLGizmoScale3D::on_render() { const Selection& selection = m_parent.get_selection(); @@ -289,6 +330,11 @@ void GLGizmoScale3D::on_render() glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); + if (m_hover_id == -1) { + lock_scalling_mode(false); + set_asymmetric_scalling_enable(false); + } + update_grabbers_data(); const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); @@ -393,8 +439,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data) if (ratio > 0.0) { m_scale(axis) = m_starting.scale(axis) * ratio; - const bool ctrl_down = wxGetKeyState(WXK_CONTROL); - if (ctrl_down && abs(ratio-1.0f)>0.001) { + if (is_asymmetric_scalling_enabled() && abs(ratio - 1.0f)>0.001) { double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis); if (m_hover_id == 2 * axis) { local_offset *= -1.0; @@ -433,8 +478,7 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const { double ratio = 0.0; - const bool ctrl_down = wxGetKeyState(WXK_CONTROL); - Vec3d pivot = (ctrl_down && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center + Vec3d pivot = (is_asymmetric_scalling_enabled() && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center Vec3d starting_vec = m_starting.drag_position - pivot; double len_starting_vec = starting_vec.norm(); if (len_starting_vec != 0.0) @@ -444,10 +488,10 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const // vector from the starting position to the found intersection Vec3d inters_vec = inters - m_starting.drag_position; - // finds projection of the vector along the staring direction - double proj = inters_vec.dot(starting_vec.normalized()); + double proj = inters_vec.norm(); + const double sign = inters_vec.dot(starting_vec) > 1e-6f ? 1.0f : -1.0f; - ratio = (len_starting_vec + proj) / len_starting_vec; + ratio = (len_starting_vec + proj * sign) / len_starting_vec; } if (wxGetKeyState(WXK_SHIFT)) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index b5ebde0cc..ef7840fcb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -69,6 +69,8 @@ public: void data_changed(bool is_serializing) override; void enable_ununiversal_scale(bool enable); BoundingBoxf3 get_bounding_box() const override; + + bool on_key(const wxKeyEvent& key_event) override; protected: virtual bool on_init() override; virtual std::string on_get_name() const override; @@ -91,8 +93,14 @@ private: double calc_ratio(const UpdateData& data) const; void update_grabbers_data(); void change_cs_by_selection(); // cs mean Coordinate System + void set_asymmetric_scalling_enable(bool is_enabled); + bool is_asymmetric_scalling_enabled() const; + void lock_scalling_mode(bool is_locked); + bool is_scalling_mode_locked() const; private: int m_last_selected_obejct_idx, m_last_selected_volume_idx; + bool m_b_asymmetric_scalling{ false }; + bool m_b_scalling_mode_locked{ false }; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 1d9d0dc2f..0b933d02d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -1395,11 +1395,13 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) int keyCode = evt.GetKeyCode(); bool processed = false; - // todo: zhimin Each gizmo should handle key event in it own on_key() function - if (m_current == Cut) { - if (GLGizmoAdvancedCut *gizmo_cut = dynamic_cast(get_current())) { - return gizmo_cut->on_key(evt); - } + auto p_current_gizmo = get_current(); + if (p_current_gizmo) { + processed = p_current_gizmo->on_key(evt); + } + if (processed) { + m_parent.set_as_dirty(); + return processed; } if (evt.GetEventType() == wxEVT_KEY_UP)