diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index d870687129..8c903470dd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -13,9 +13,7 @@ #include -namespace Slic3r { - -namespace GUI { +namespace Slic3r::GUI { @@ -164,7 +162,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::Separator(); if (m_imgui->button(m_desc.at("remove_all"))) { - Plater::TakeSnapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); ModelObject* mo = m_c->selection_info()->model_object(); int idx = -1; for (ModelVolume* mv : mo->volumes) { @@ -248,9 +246,10 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); - float clp_dist = m_c->object_clipper()->get_position(); + auto clp_dist = float(m_c->object_clipper()->get_position()); if (ImGui::SliderFloat(" ", &clp_dist, 0.f, 1.f, "%.2f")) - m_c->object_clipper()->set_position(clp_dist, true); + m_c->object_clipper()->set_position(clp_dist, true); + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); @@ -265,7 +264,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) { - float threshold = (M_PI/180.)*threshold_deg; + float threshold = (float(M_PI)/180.f)*threshold_deg; const Selection& selection = m_parent.get_selection(); const ModelObject* mo = m_c->selection_info()->model_object(); const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; @@ -297,7 +296,7 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) activate_internal_undo_redo_stack(true); - Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle") + Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle") : _L("Add supports by angle")); update_model_object(); m_parent.set_as_dirty(); @@ -356,6 +355,18 @@ PainterGizmoType GLGizmoFdmSupports::get_painter_type() const return PainterGizmoType::FDM_SUPPORTS; } +wxString GLGizmoFdmSupports::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const +{ + wxString action_name; + if (shift_down) + action_name = _L("Remove selection"); + else { + if (button_down == Button::Left) + action_name = _L("Add supports"); + else + action_name = _L("Block supports"); + } + return action_name; +} -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index 41e4cc514b..019ed15f40 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -3,9 +3,7 @@ #include "GLGizmoPainterBase.hpp" -namespace Slic3r { - -namespace GUI { +namespace Slic3r::GUI { class GLGizmoFdmSupports : public GLGizmoPainterBase { @@ -19,6 +17,8 @@ protected: void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; + wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + private: bool on_init() override; @@ -39,8 +39,7 @@ private: -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI #endif // slic3r_GLGizmoFdmSupports_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 62ff7c66b8..4e90446afb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/BitmapCache.hpp" +#include "slic3r/GUI/format.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/Model.hpp" @@ -105,193 +106,6 @@ void GLGizmoMmuSegmentation::render_painter_gizmo() const glsafe(::glDisable(GL_BLEND)); } -bool GLGizmoMmuSegmentation::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) -{ - if (action == SLAGizmoEventType::MouseWheelUp - || action == SLAGizmoEventType::MouseWheelDown) { - if (control_down) { - double pos = m_c->object_clipper()->get_position(); - pos = action == SLAGizmoEventType::MouseWheelDown - ? std::max(0., pos - 0.01) - : std::min(1., pos + 0.01); - m_c->object_clipper()->set_position(pos, true); - return true; - } - else if (alt_down) { - m_cursor_radius = action == SLAGizmoEventType::MouseWheelDown - ? std::max(m_cursor_radius - CursorRadiusStep, CursorRadiusMin) - : std::min(m_cursor_radius + CursorRadiusStep, CursorRadiusMax); - m_parent.set_as_dirty(); - return true; - } - } - - if (action == SLAGizmoEventType::ResetClippingPlane) { - m_c->object_clipper()->set_position(-1., false); - return true; - } - - if (action == SLAGizmoEventType::LeftDown - || action == SLAGizmoEventType::RightDown - || (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) { - - if (m_triangle_selectors.empty()) - return false; - - EnforcerBlockerType new_state = EnforcerBlockerType::NONE; - if (! shift_down) { - if (action == SLAGizmoEventType::Dragging) - new_state = m_button_down == Button::Left - ? EnforcerBlockerType(m_first_selected_extruder_idx) - : EnforcerBlockerType(m_second_selected_extruder_idx); - else - new_state = action == SLAGizmoEventType::LeftDown - ? EnforcerBlockerType(m_first_selected_extruder_idx) - : EnforcerBlockerType(m_second_selected_extruder_idx); - } - - const Camera& camera = wxGetApp().plater()->get_camera(); - const Selection& selection = m_parent.get_selection(); - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; - const Transform3d& instance_trafo = mi->get_transformation().get_matrix(); - - // List of mouse positions that will be used as seeds for painting. - std::vector mouse_positions{mouse_position}; - - // In case current mouse position is far from the last one, - // add several positions from between into the list, so there - // are no gaps in the painted region. - { - if (m_last_mouse_click == Vec2d::Zero()) - m_last_mouse_click = mouse_position; - // resolution describes minimal distance limit using circle radius - // as a unit (e.g., 2 would mean the patches will be touching). - double resolution = 0.7; - double diameter_px = resolution * m_cursor_radius * camera.get_zoom(); - int patches_in_between = int(((mouse_position - m_last_mouse_click).norm() - diameter_px) / diameter_px); - if (patches_in_between > 0) { - Vec2d diff = (mouse_position - m_last_mouse_click)/(patches_in_between+1); - for (int i=1; i<=patches_in_between; ++i) - mouse_positions.emplace_back(m_last_mouse_click + i*diff); - } - } - m_last_mouse_click = Vec2d::Zero(); // only actual hits should be saved - - // Precalculate transformations of individual meshes. - std::vector trafo_matrices; - for (const ModelVolume* mv : mo->volumes) { - if (mv->is_model_part()) - trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); - } - - // Now "click" into all the prepared points and spill paint around them. - for (const Vec2d& mp : mouse_positions) { - update_raycast_cache(mp, camera, trafo_matrices); - - bool dragging_while_painting = (action == SLAGizmoEventType::Dragging && m_button_down != Button::None); - - // The mouse button click detection is enabled when there is a valid hit. - // Missing the object entirely - // shall not capture the mouse. - if (m_rr.mesh_id != -1) { - if (m_button_down == Button::None) - m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right); - } - - if (m_rr.mesh_id == -1) { - // In case we have no valid hit, we can return. The event will be stopped when - // dragging while painting (to prevent scene rotations and moving the object) - return dragging_while_painting; - } - - const Transform3d& trafo_matrix = trafo_matrices[m_rr.mesh_id]; - - // Calculate direction from camera to the hit (in mesh coords): - Vec3f camera_pos = (trafo_matrix.inverse() * camera.get_position()).cast(); - - assert(m_rr.mesh_id < int(m_triangle_selectors.size())); - if (m_seed_fill_enabled) - m_triangle_selectors[m_rr.mesh_id]->seed_fill_apply_on_triangles(new_state); - else - m_triangle_selectors[m_rr.mesh_id]->select_patch(m_rr.hit, int(m_rr.facet), camera_pos, m_cursor_radius, m_cursor_type, - new_state, trafo_matrix, m_triangle_splitting_enabled); - m_last_mouse_click = mouse_position; - } - - return true; - } - - if (action == SLAGizmoEventType::Moving && m_seed_fill_enabled) { - if (m_triangle_selectors.empty()) - return false; - - const Camera & camera = wxGetApp().plater()->get_camera(); - const Selection & selection = m_parent.get_selection(); - const ModelObject * mo = m_c->selection_info()->model_object(); - const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - const Transform3d & instance_trafo = mi->get_transformation().get_matrix(); - - // Precalculate transformations of individual meshes. - std::vector trafo_matrices; - for (const ModelVolume *mv : mo->volumes) - if (mv->is_model_part()) - trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); - - // Now "click" into all the prepared points and spill paint around them. - update_raycast_cache(mouse_position, camera, trafo_matrices); - - if (m_rr.mesh_id == -1) { - // Clean selected by seed fill for all triangles - for (auto &triangle_selector : m_triangle_selectors) - triangle_selector->seed_fill_unselect_all_triangles(); - - // In case we have no valid hit, we can return. - return false; - } - - assert(m_rr.mesh_id < int(m_triangle_selectors.size())); - m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_seed_fill_angle); - return true; - } - - if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp) - && m_button_down != Button::None) { - // Take snapshot and update ModelVolume data. - wxString action_name; - if (get_painter_type() == PainterGizmoType::FDM_SUPPORTS) { - if (shift_down) - action_name = _L("Remove selection"); - else { - if (m_button_down == Button::Left) - action_name = _L("Add supports"); - else - action_name = _L("Block supports"); - } - } - if (get_painter_type() == PainterGizmoType::SEAM) { - if (shift_down) - action_name = _L("Remove selection"); - else { - if (m_button_down == Button::Left) - action_name = _L("Enforce seam"); - else - action_name = _L("Block seam"); - } - } - - activate_internal_undo_redo_stack(true); - Plater::TakeSnapshot snapshot(wxGetApp().plater(), action_name); - update_model_object(); - - m_button_down = Button::None; - m_last_mouse_click = Vec2d::Zero(); - return true; - } - - return false; -} - void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) { GLGizmoPainterBase::set_painter_gizmo_data(selection); @@ -681,4 +495,16 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui) } } +wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const +{ + wxString action_name; + if (shift_down) + action_name = _L("Remove painted color"); + else { + size_t extruder_id = (button_down == Button::Left ? m_first_selected_extruder_idx : m_second_selected_extruder_idx) + 1; + action_name = GUI::format(_L("Painted using: Extruder %1%"), extruder_id); + } + return action_name; +} + } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 72e09100e9..82b858d421 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -29,19 +29,22 @@ public: void render_painter_gizmo() const override; - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; - void set_painter_gizmo_data(const Selection& selection) override; protected: std::array get_cursor_sphere_left_button_color() const override; std::array get_cursor_sphere_right_button_color() const override; + EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx); } + EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx); } + void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; bool on_is_selectable() const override; + wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + size_t m_first_selected_extruder_idx = 0; size_t m_second_selected_extruder_idx = 1; std::vector m_original_extruders_names; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index ec3a7c4d96..db7913fc12 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -330,13 +330,9 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous EnforcerBlockerType new_state = EnforcerBlockerType::NONE; if (! shift_down) { if (action == SLAGizmoEventType::Dragging) - new_state = m_button_down == Button::Left - ? EnforcerBlockerType::ENFORCER - : EnforcerBlockerType::BLOCKER; + new_state = m_button_down == Button::Left ? this->get_left_button_state_type() : this->get_right_button_state_type(); else - new_state = action == SLAGizmoEventType::LeftDown - ? EnforcerBlockerType::ENFORCER - : EnforcerBlockerType::BLOCKER; + new_state = action == SLAGizmoEventType::LeftDown ? this->get_left_button_state_type() : this->get_right_button_state_type(); } const Camera& camera = wxGetApp().plater()->get_camera(); @@ -447,30 +443,9 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp) && m_button_down != Button::None) { // Take snapshot and update ModelVolume data. - wxString action_name; - if (get_painter_type() == PainterGizmoType::FDM_SUPPORTS) { - if (shift_down) - action_name = _L("Remove selection"); - else { - if (m_button_down == Button::Left) - action_name = _L("Add supports"); - else - action_name = _L("Block supports"); - } - } - if (get_painter_type() == PainterGizmoType::SEAM) { - if (shift_down) - action_name = _L("Remove selection"); - else { - if (m_button_down == Button::Left) - action_name = _L("Enforce seam"); - else - action_name = _L("Block seam"); - } - } - + wxString action_name = this->handle_snapshot_action_name(shift_down, m_button_down); activate_internal_undo_redo_stack(true); - Plater::TakeSnapshot(wxGetApp().plater(), action_name); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), action_name); update_model_object(); m_button_down = Button::None; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index eb8a7e053b..8e2d05ea83 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -7,16 +7,13 @@ #include "libslic3r/ObjectID.hpp" #include "libslic3r/TriangleSelector.hpp" +#include "libslic3r/Model.hpp" #include -namespace Slic3r { - -enum class EnforcerBlockerType : int8_t; - -namespace GUI { +namespace Slic3r::GUI { enum class SLAGizmoEventType : unsigned char; class ClippingPlane; @@ -90,6 +87,9 @@ protected: virtual std::array get_cursor_sphere_left_button_color() const { return {0.f, 0.f, 1.f, 0.25f}; } virtual std::array get_cursor_sphere_right_button_color() const { return {1.f, 0.f, 0.f, 0.25f}; } + virtual EnforcerBlockerType get_left_button_state_type() const { return EnforcerBlockerType::ENFORCER; } + virtual EnforcerBlockerType get_right_button_state_type() const { return EnforcerBlockerType::BLOCKER; } + float m_cursor_radius = 2.f; static constexpr float CursorRadiusMin = 0.4f; // cannot be zero static constexpr float CursorRadiusMax = 8.f; @@ -104,6 +104,12 @@ protected: bool m_seed_fill_enabled = false; float m_seed_fill_angle = 0.f; + enum class Button { + None, + Left, + Right + }; + private: bool is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const; void update_raycast_cache(const Vec2d& mouse_position, @@ -116,12 +122,6 @@ private: bool m_schedule_update = false; Vec2d m_last_mouse_click = Vec2d::Zero(); - enum class Button { - None, - Left, - Right - }; - Button m_button_down = Button::None; EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) @@ -151,11 +151,12 @@ protected: void on_save(cereal::BinaryOutputArchive& ar) const override {} CommonGizmosDataID on_get_requirements() const override; + virtual wxString handle_snapshot_action_name(bool shift_down, Button button_down) const = 0; + friend class ::Slic3r::GUI::GLGizmoMmuSegmentation; }; -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI #endif // slic3r_GLGizmoPainterBase_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 9724767550..7a274c9270 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -12,9 +12,7 @@ #include -namespace Slic3r { - -namespace GUI { +namespace Slic3r::GUI { @@ -115,7 +113,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) m_imgui->text(""); if (m_imgui->button(m_desc.at("remove_all"))) { - Plater::TakeSnapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), wxString(_L("Reset selection"))); ModelObject* mo = m_c->selection_info()->model_object(); int idx = -1; for (ModelVolume* mv : mo->volumes) { @@ -194,9 +192,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); - float clp_dist = m_c->object_clipper()->get_position(); + auto clp_dist = float(m_c->object_clipper()->get_position()); if (ImGui::SliderFloat(" ", &clp_dist, 0.f, 1.f, "%.2f")) - m_c->object_clipper()->set_position(clp_dist, true); + m_c->object_clipper()->set_position(clp_dist, true); + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::PushTextWrapPos(max_tooltip_width); @@ -260,7 +259,18 @@ PainterGizmoType GLGizmoSeam::get_painter_type() const return PainterGizmoType::SEAM; } +wxString GLGizmoSeam::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const +{ + wxString action_name; + if (shift_down) + action_name = _L("Remove selection"); + else { + if (button_down == Button::Left) + action_name = _L("Enforce seam"); + else + action_name = _L("Block seam"); + } + return action_name; +} - -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index dfadec0da7..d97bad10ff 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -3,9 +3,7 @@ #include "GLGizmoPainterBase.hpp" -namespace Slic3r { - -namespace GUI { +namespace Slic3r::GUI { class GLGizmoSeam : public GLGizmoPainterBase { @@ -20,6 +18,8 @@ protected: std::string on_get_name() const override; PainterGizmoType get_painter_type() const override; + wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + private: bool on_init() override; @@ -36,8 +36,7 @@ private: -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI #endif // slic3r_GLGizmoSeam_hpp_