From 94f3aaacd402cd12d9b54dcdf404866c3516ac5a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 2 May 2022 12:44:47 +0200 Subject: [PATCH] Cut WIP: Undo/Redo implementation --- resources/localization/list.txt | 5 ++ src/libslic3r/Model.hpp | 3 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 91 +++++++++++++++++++++---- src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 18 +++-- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 3 +- src/slic3r/GUI/Plater.cpp | 5 +- 6 files changed, 100 insertions(+), 25 deletions(-) diff --git a/resources/localization/list.txt b/resources/localization/list.txt index d68f99bff..f02b017d7 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -17,16 +17,21 @@ src/slic3r/GUI/GalleryDialog.cpp src/slic3r/GUI/GCodeViewer.cpp src/slic3r/GUI/GLCanvas3D.cpp src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +src/slic3r/GUI/Gizmos/GLGizmoCut.hpp src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp src/slic3r/GUI/Gizmos/GLGizmoMove.cpp src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp src/slic3r/GUI/Gizmos/GLGizmoScale.cpp src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp src/slic3r/GUI/Gizmos/GLGizmosManager.cpp src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp src/slic3r/GUI/GUI.cpp diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 108e30511..871859cf0 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -584,7 +584,8 @@ private: Internal::StaticSerializationWrapper layer_heigth_profile_wrapper(layer_height_profile); ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper, sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation, - m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid); + m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid, + cut_connectors, cut_id); } // Called by Print::validate() from the UI thread. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 4065c2060..6fafdbf9b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -14,6 +14,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp" +#include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/AppConfig.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/TriangleMeshSlicer.hpp" @@ -88,6 +89,8 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event) return false; if (m_rotation_gizmo.on_mouse(mouse_event)) { + if (mouse_event.LeftUp()) + on_stop_dragging(); update_clipper(); return true; } @@ -221,7 +224,7 @@ void GLGizmoCut3D::update_clipper() void GLGizmoCut3D::update_clipper_on_render() { update_clipper(); - suppress_update_clipper_on_render = true; + force_update_clipper_on_render = false; } void GLGizmoCut3D::set_center(const Vec3d& center) @@ -595,6 +598,27 @@ bool GLGizmoCut3D::on_init() return true; } +void GLGizmoCut3D::on_load(cereal::BinaryInputArchive& ar) +{ + ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, //m_selected, + m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id, + m_ar_plane_center, m_ar_rotations); + + set_center_pos(m_ar_plane_center); + m_rotation_gizmo.set_center(m_ar_plane_center); + m_rotation_gizmo.set_rotation(m_ar_rotations); + force_update_clipper_on_render = true; + + m_parent.request_extra_frame(); +} + +void GLGizmoCut3D::on_save(cereal::BinaryOutputArchive& ar) const +{ + ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, //m_selected, + m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id, + m_ar_plane_center, m_ar_rotations); +} + std::string GLGizmoCut3D::on_get_name() const { return _u8L("Cut"); @@ -602,13 +626,22 @@ std::string GLGizmoCut3D::on_get_name() const void GLGizmoCut3D::on_set_state() { - if (get_state() == On) + if (m_state == On) { update_bb(); + // initiate archived values + m_ar_plane_center = m_plane_center; + m_ar_rotations = m_rotation_gizmo.get_rotation(); + + m_parent.request_extra_frame(); + } + else + m_c->object_clipper()->release(); + m_rotation_gizmo.set_center(m_plane_center); m_rotation_gizmo.set_state(m_state); - suppress_update_clipper_on_render = m_state != On; + force_update_clipper_on_render = m_state == On; } void GLGizmoCut3D::on_set_hover_id() @@ -674,6 +707,24 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data) } } +void GLGizmoCut3D::on_start_dragging() +{ + if (m_hover_id > m_group_id && m_connector_mode == CutConnectorMode::Manual) + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move connector"), UndoRedo::SnapshotType::GizmoAction); +} + +void GLGizmoCut3D::on_stop_dragging() +{ + if (m_hover_id < m_group_id) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Rotate cut plane"), UndoRedo::SnapshotType::GizmoAction); + m_ar_rotations = m_rotation_gizmo.get_rotation(); + } + else if (m_hover_id == m_group_id) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move cut plane"), UndoRedo::SnapshotType::GizmoAction); + m_ar_plane_center = m_plane_center; + } +} + void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos) { m_plane_center = center_pos; @@ -778,6 +829,9 @@ void GLGizmoCut3D::on_render() if (!m_sphere.is_initialized()) m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0)); + if (force_update_clipper_on_render) + update_clipper_on_render(); + render_connectors(false); m_c->object_clipper()->render_cut(); @@ -790,9 +844,6 @@ void GLGizmoCut3D::on_render() m_rotation_gizmo.render(); } } - - if (!suppress_update_clipper_on_render) - update_clipper_on_render(); } void GLGizmoCut3D::on_render_for_picking() @@ -963,7 +1014,7 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit) ImGui::Separator(); - m_imgui->disabled_begin((!m_keep_upper && !m_keep_lower) || !can_perform_cut()); + m_imgui->disabled_begin(!can_perform_cut()); const bool cut_clicked = m_imgui->button(_L("Perform cut")); m_imgui->disabled_end(); @@ -1024,13 +1075,16 @@ void GLGizmoCut3D::render_connectors(bool picking) { m_has_invalid_connector = false; - if (m_connector_mode == CutConnectorMode::Auto) + if (m_connector_mode == CutConnectorMode::Auto || !m_c->selection_info()) return; const ModelObject* mo = m_c->selection_info()->model_object(); const CutConnectors& connectors = mo->cut_connectors; - if (connectors.size() != m_selected.size()) - return; + if (connectors.size() != m_selected.size()) { + // #ysFIXME + m_selected.clear(); + m_selected.resize(connectors.size(), false); + } #if ENABLE_LEGACY_OPENGL_REMOVAL GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); @@ -1145,7 +1199,7 @@ void GLGizmoCut3D::render_connectors(bool picking) bool GLGizmoCut3D::can_perform_cut() const { - if (m_has_invalid_connector) + if (m_has_invalid_connector || (!m_keep_upper && !m_keep_lower)) return false; BoundingBoxf3 box = bounding_box(); @@ -1172,9 +1226,16 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) Vec3d cut_center_offset = m_plane_center - instance_offset; cut_center_offset[Z] -= first_glvolume->get_sla_shift_z(); + Plater* plater = wxGetApp().plater(); + bool create_dowels_as_separate_object = false; if (0.0 < object_cut_z && can_perform_cut()) { - ModelObject* mo = wxGetApp().plater()->model().objects[object_idx]; + ModelObject* mo = plater->model().objects[object_idx]; + if(!mo) + return; + + Plater::TakeSnapshot snapshot(plater, _L("Cut by Plane")); + const bool has_connectors = !mo->cut_connectors.empty(); // update connectors pos as offset of its center before cut performing if (has_connectors && m_connector_mode == CutConnectorMode::Manual) { @@ -1198,7 +1259,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) create_dowels_as_separate_object = true; } - wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(), + plater->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(), only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) | only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) | only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) | @@ -1306,7 +1367,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi const Vec3d& normal = pos_and_normal.second; // The clipping plane was clicked, hit containts coordinates of the hit in world coords. std::cout << hit.x() << "\t" << hit.y() << "\t" << hit.z() << std::endl; - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector")); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction); connectors.emplace_back(hit, m_rotation_gizmo.get_rotation(), float(m_connector_size * 0.5), float(m_connector_depth_ratio)); update_model_object(); @@ -1326,7 +1387,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi if (m_hover_id < m_connectors_group_id) return false; - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Delete connector")); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Delete connector"), UndoRedo::SnapshotType::GizmoAction); size_t connector_id = m_hover_id - m_connectors_group_id; connectors.erase(connectors.begin() + connector_id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index cb6d222ef..f8935d61f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -24,6 +24,10 @@ class GLGizmoCut3D : public GLGizmoBase double m_snap_step{ 1.0 }; int m_connectors_group_id; + // archived values + Vec3d m_ar_plane_center { Vec3d::Zero() }; + Vec3d m_ar_rotations { Vec3d::Zero() }; + Vec3d m_plane_center{ Vec3d::Zero() }; // data to check position of the cut palne center on gizmo activation Vec3d m_min_pos{ Vec3d::Zero() }; @@ -38,7 +42,7 @@ class GLGizmoCut3D : public GLGizmoBase #if ENABLE_LEGACY_OPENGL_REMOVAL GLModel m_plane; - GLModel m_grabber_connection; +// GLModel m_grabber_connection; GLModel m_cone; GLModel m_sphere; Vec3d m_old_center; @@ -57,7 +61,7 @@ class GLGizmoCut3D : public GLGizmoBase float m_label_width{ 150.0 }; float m_control_width{ 200.0 }; bool m_imperial_units{ false }; - bool suppress_update_clipper_on_render{false}; + bool force_update_clipper_on_render{false}; mutable std::vector m_selected; // which pins are currently selected bool m_selection_empty = true; @@ -123,18 +127,24 @@ public: protected: bool on_init() override; - void on_load(cereal::BinaryInputArchive& ar) override { ar(m_keep_upper, m_keep_lower, m_rotate_lower); } - void on_save(cereal::BinaryOutputArchive& ar) const override { ar(m_keep_upper, m_keep_lower, m_rotate_lower); } + void on_load(cereal::BinaryInputArchive& ar) override; + void on_save(cereal::BinaryOutputArchive& ar) const override; std::string on_get_name() const override; void on_set_state() override; CommonGizmosDataID on_get_requirements() const override; void on_set_hover_id() override; bool on_is_activable() const override; void on_dragging(const UpdateData& data) override; + void on_start_dragging() override; + void on_stop_dragging() override; void on_render() override; void on_render_for_picking() override; void on_render_input_window(float x, float y, float bottom_limit) override; + bool wants_enter_leave_snapshots() const override { return true; } + std::string get_gizmo_entering_text() const override { return _u8L("Entering Cut gizmo"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Cut gizmo"); } + std::string get_action_snapshot_name() override { return _u8L("Cut gizmo editing"); } private: void set_center(const Vec3d& center); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index a5848013b..41f681894 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -836,7 +836,8 @@ void GLGizmoRotate3D::on_start_dragging() void GLGizmoRotate3D::on_stop_dragging() { assert(0 <= m_hover_id && m_hover_id < 3); - m_parent.do_rotate(L("Gizmo-Rotate")); + if (!m_use_only_grabbers) + m_parent.do_rotate(L("Gizmo-Rotate")); m_gizmos[m_hover_id].stop_dragging(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 00f2aee17..00274dfb5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5915,10 +5915,7 @@ void Slic3r::GUI::Plater::cut(size_t obj_idx, size_t instance_idx, const Vec3d& wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds"); - if (!attributes.has(ModelObjectCutAttribute::KeepUpper) && !attributes.has(ModelObjectCutAttribute::KeepLower)) - return; - - Plater::TakeSnapshot snapshot(this, _L("Cut by Plane")); + //Plater::TakeSnapshot snapshot(this, _L("Cut by Plane")); wxBusyCursor wait; const auto new_objects = object->cut(instance_idx, cut_center, cut_rotation, attributes);